算法修炼Day05|一周小结

86 阅读5分钟

数组系列:二分法

题目:704. 二分查找 - 力扣(LeetCode)

代码实现

class Solution {
    public int search(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                return i;
            }
        }
        return -1;
    }
}
class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = (right + left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}

题目:27. 移除元素 - 力扣(LeetCode)

代码实现

class Solution {
    public int removeElement(int[] nums, int val) {
        int index = 0;
        for (int num : nums) {
            if (num != val) {
                nums[index] = num;
                index++;
            }
        }
        return index;
    }
}

class Solution {
    public int removeElement(int[] nums, int val) {
        // 双指针:快指针遍历获取不等于val的元素,慢指针负责更新
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}

题目:977. 有序数组的平方 - 力扣(LeetCode)

代码实现:

// class Solution {
//     public int[] sortedSquares(int[] nums) {
//         for (int i = 0; i < nums.length; i++) {
//             nums[i] = nums[i] * nums[i];
//         }
//         Arrays.sort(nums);
//         return nums;
//     }
// }

class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] ans = new int[nums.length];
        int left = 0, right = nums.length - 1;
        int index = ans.length - 1;
        while (left <= right) {
            int leftSum = nums[left] * nums[left];
            int rightSum = nums[right] * nums[right];
            if (leftSum > rightSum) {
                ans[index] = leftSum;
                left++;
            } else {
                ans[index] = rightSum;
                right--;
            }
            index--;
        }
        return ans;
    }
}

题目:209. 长度最小的子数组 - 力扣(LeetCode)

代码实现

// class Solution {
//     public int minSubArrayLen(int target, int[] nums) {
//         // 暴力超时
//         int ans = 1000000;
//         for (int i = 0; i < nums.length; i++) {
//             int sum = 0;
//             int len = 0;
//             for (int j = i; j < nums.length; j++) {
//                 sum += nums[j];
//                 if (sum >= target) {
//                     len = j - i + 1;
//                     ans = ans > len ? len : ans;
//                     break;
//                 }
//             }
//         }
//         return ans == 1000000 ? 0 : ans;
//     }
// }
// 

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // 滑动窗口:左侧缩小范围,右侧遍历扩展
        int left = 0;
        int ans = 1000000;
        int len = 0;
        int sum = 0;
        for (int right = left; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= target) {
                len = right - left + 1;
                ans = Math.min(ans, len);
                sum -= nums[left];
                left++;
            }
        }
        return ans == 1000000 ? 0 : ans;
    }
}

题目:59. 螺旋矩阵 II - 力扣(LeetCode)

代码实现


class Solution {
    public int[][] generateMatrix(int n) {
        int total = n * n;
        int start = 1;
        int l = 0, r = n - 1, t = 0, b = n - 1;
        int[][] ans = new int[n][n];

        while (start <= total) {
            // 上侧:从左到右
            for (int i = l; i <= r; i++) {
                ans[t][i] = start++;
            }
            t++;

            // 右侧:从上到下
            for (int i = t; i <= b; i++) {
                ans[i][r] = start++;
            }
            r--;
            // 下侧:从右到左
            for (int i = r; i >= l; i--) {
                ans[b][i] = start++;
            }
            b--;
            
            // 左侧:从下到上
            for (int i = b; i >= t; i--) {
                ans[i][l] = start++;
            }
            l++;

        }
        return ans;
    }
}

链表系列:虚拟头节点

题目:203. 移除链表元素 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode dummyHead = new ListNode(0, head);
        ListNode cur = dummyHead;
        while (cur.next != null) {
            if (cur.next.val == val) {
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        return dummyHead.next;
    }
}

题目:707. 设计链表 - 力扣(LeetCode)

代码实现

// 细节还值得挖一挖
class ListNode {
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val) {
        this.val = val;
    }
    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

class MyLinkedList {
    int size;
    ListNode head;
    
    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }
    
    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1; // 非法值返回 -1
        }
        ListNode cur = head;
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size, val);
    }
    
    public void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        if (index < 0) {
            index = 0;
        }
        size++;
        ListNode prev = head;
        for (int i = 0; i < index; i++) {
            prev = prev.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next = prev.next;
        prev.next = toAdd;
    }
    
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        ListNode prev = head; 
        for (int i = 0; i < index; i++) {
            prev = prev.next;
        }
        prev.next = prev.next.next;
    }
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */

题目:206. 反转链表 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null, cur = head;
        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = prev;
            prev = cur;
            cur = temp;
        }
        return prev;
    }
}

题目:24. 两两交换链表中的节点 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(0, head);
        ListNode prev = dummyHead;
        while (prev.next != null && prev.next.next != null) {
            ListNode start = prev.next;
            ListNode end = prev.next.next;
            prev.next = start.next;
            start.next = end.next;
            end.next = start;
            prev = start;
        }
        return dummyHead.next;
    }
}

题目:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 双指针
        ListNode dummyHead = new ListNode(0, head);
        ListNode slowIndex = dummyHead;
        ListNode fastIndex = dummyHead;
        for (int i = 0; i < n; i++) {
            fastIndex = fastIndex.next;
        }
        while (fastIndex.next != null) {
            slowIndex = slowIndex.next;
            fastIndex = fastIndex.next;
        }
        slowIndex.next = slowIndex.next.next;
        return dummyHead.next;
    }
}

题目:面试题 02.07. 链表相交 - 力扣(LeetCode)

代码实现

// 大意!!!!
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 链表相交,尾部对齐
        // 求长度
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != null) {
            lenA++;
            curA = curA.next;
        }
        while (curB != null) {
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        // 将较长的给A
        if (lenB > lenA) {
            int temp = lenA;
            lenA = lenB;
            lenB = temp;
            ListNode tempNode = curA;
            curA = curB;
            curB = tempNode;
        }
        int diff = lenA - lenB;
        while (diff-- > 0) {
            curA = curA.next;
        }
        while (curA != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }
}

题目:206. 反转链表 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        while (cur != null) {
            ListNode temp = cur.next;
            cur.next = prev;
            prev = cur;
            cur = temp;
        }
        return prev;
    }
}

题目:24. 两两交换链表中的节点 - 力扣(LeetCode)

方法:定义虚拟头节点做结果输出(能避免对头节点的特殊处理),定义前驱节点,对后继节点进行判空,start和end对后面两个节点进行记录,循环过程中进行交换。

代码实现

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(0, head);
        ListNode prev = dummyHead;
        while (prev.next != null && prev.next.next != null) {
            ListNode start = prev.next;
            ListNode end = prev.next.next;
            prev.next = start.next;
            start.next = end.next;
            end.next = start;
            prev = start;
        }
        return dummyHead.next;
    }
}

题目:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

代码实现

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 双指针
        // 虚拟头节点
        ListNode dummyHead = new ListNode(0, head);
        ListNode start = dummyHead;
        ListNode end = dummyHead;
        for (int i = 0; i < n; i++) {
            start = start.next;
        }
        while (start.next != null) {
            start = start.next;
            end = end.next;
        }
        end.next = end.next.next;
        return dummyHead.next;
    }
}

题目:面试题 02.07. 链表相交 - 力扣(LeetCode)

计算链表长度,指定一个较长的,将较长的进行后移两链表差值的节点数,再一次遍历进行判等。

代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 相交之后的特性是尾部对齐
        // 计算链表长度,指定一个较长的,将较长的进行后移两链表差值的节点数,再一次遍历进行判等
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != null) {
            curA = curA.next;
            lenA++;
        }
        while (curB != null) {
            curB = curB.next;
            lenB++;
        }
        curA = headA;
        curB = headB;
        if (lenB > lenA) {
            int temp = lenA;
            lenA = lenB;
            lenB = temp;
            ListNode tempNode = curA;
            curA = curB;
            curB = tempNode;
        }
        int gap = lenA - lenB;
        while (gap > 0) {
            curA = curA.next;
            gap--;
        }
        while (curA != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }
}

题目:142. 环形链表 II - 力扣(LeetCode)

代码实现

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                slow = head;
                while (slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return fast;
            }
        }
        return null;
    }
}