算法通关村第一关——常见例题

78 阅读2分钟

1.两个链表第一个公共子节点

方法 1:暴力

暴力法遍历第一个链表的每个节点,对每个节点检查第二个链表,找到共同节点。复杂度为 O(m*n)。

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode head1 = pHead1;
        while(head1!=null){
             ListNode head2 = pHead2;
            while(head2!=null){
                if(head1.equals(head2)){
                    return head2;
                }else{
                    head2 = head2.next;
                }
            }
            head1 = head1.next;
        }
        return head1;
    }
}

方法2:栈

使用两个栈分别存储两链表节点,从尾部开始比较,直至找到最后一个共同节点。时间复杂度为 O(m + n)。

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        Stack<ListNode> stack1 = new Stack<>();
        Stack<ListNode> stack2 = new Stack<>();

        // 将第一个链表的所有节点压入栈1
        while (pHead1 != null) {
            stack1.push(pHead1);
            pHead1 = pHead1.next;
        }

        // 将第二个链表的所有节点压入栈2
        while (pHead2 != null) {
            stack2.push(pHead2);
            pHead2 = pHead2.next;
        }

        ListNode lastCommon = null;

        // 比较两个栈的栈顶元素
        while (!stack1.isEmpty() && !stack2.isEmpty()) {
            if (stack1.peek() == stack2.peek()) {
                lastCommon = stack1.peek();
                stack1.pop();
                stack2.pop();
            } else {
                break;
            }
        }

        return lastCommon; // 返回最后一个共同节点
    }
}

方法3:用HashMap

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        
        HashMap<ListNode, Boolean> map = new HashMap<>();
 
        // 将第一个链表的节点存储在HashMap中
        ListNode current = pHead1;
        while (current != null) {
            map.put(current, true);
            current = current.next;
        }
 
        // 检查第二个链表的节点是否存在于HashMap中
        current = pHead2;
        while (current != null) {
            if (map.containsKey(current)) {
                return current; // 找到第一个公共子节点
            }
            current = current.next;
        }
 
        return current; // 没有公共子节点
    }
}

方法4:用HashSet

public class Solution {
    public ListNode findFirstCommonNodeBySet(ListNode headA, ListNode headB) {
        Set<ListNode> set = new HashSet<>();

        while (headA != null) {
            set.add(headA);
            headA = headA.next;
        }

        while (headB != null) {
            if (set.contains(headB)) {
                return headB;
            }
            headB = headB.next;
        }

        return null;
    }
}

2.判断是否为回文字符串

方法1: 数组 for-loop

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param str string字符串 待判断的字符串
     * @return bool布尔型
     */
    public boolean judge (String str) {
        char[] chars = str.toCharArray();
        int maxSize = chars.length / 2; 
        for (int i = 0; i < maxSize; i++) {
            if (chars[i] != chars[chars.length - 1 - i]) {
                return false;
            }
        }
        return true;
    }
}

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param ListNode head
     * @return bool布尔型
     */
    public boolean judge (ListNode head) {

        if (head == null) {
            return true; // 空链表默认为回文
        }

        // 计算链表长度
        int length = 0;
        ListNode temp = head;
        while (temp != null) {
            length++;
            temp = temp.next;
        }

        // 初始化数组并填充链表的值
        int[] values = new int[length];
        temp = head;
        int index = 0;
        while (temp != null) {
            values[index++] = temp.val;
            temp = temp.next;
        }

        // 判断是否回文
        int halfLength = length / 2;
        for (int i = 0; i < halfLength; i++) {
            if (values[i] != values[length - 1 - i]) {
                return false;
            }
        }

        return true;
    }

}

方法1.1 ArrayList(动态长度变化)

import java.util.ArrayList;

public boolean judge(ListNode head) {
    ArrayList<Integer> list = new ArrayList<>();
    ListNode temp = head;
    
    while(temp != null) {
        list.add(temp.val);
        temp = temp.next;
    }
    
    int maxSize = list.size() / 2;
    for (int i = 0; i < maxSize; i++) {
        if (!list.get(i).equals(list.get(list.size() - 1 - i))) {
            return false;
        }
    }
    return true;
}

方法2.0:全压栈,全比完

public boolean isPalindrome(ListNode head) {
   ListNode temp = head;
   Stack<Integer> stack = new Stack<>();
   // 把链表节点的值压入栈中
   while (temp != null) {
       stack.push(temp.val);
       temp = temp.next;
   }
   // 之后一边出栈,一边比较
   while (head != null) {
       if (head.val != stack.pop()) {
           return false;
       }
       head = head.next;
   }
   return true;
}