leetcode秋招刷题总结

LRU

题目

import java.util.HashMap;

class LRUCache {
    public static class Node {
        Node next, pre;
        int key, val;

        Node(int k, int v) {
            //少了这两行会报空指针
            next = this;
            pre = this;
            key = k;
            val = v;
        }
    }

    HashMap<Integer, Node> map = new HashMap<>();
    int capacity;
    Node head;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new Node(0, 0);
    }

    public int get(int key) {
        /**
         * 1、判断map包不包含key,
         * 2.1 不包含return -1
         * 2.2包含的话refresh放到链表前面,返回node.val
         */
        if (!map.containsKey(key)) return -1;
        Node node = map.get(key);
        refresh(node);
        return node.val;
    }

    public void put(int key, int value) {

        /**
         * 1、先判断包不包含key
         * 2.1 包含则更新node.val,然后refresh到前面
         * 2.2 不包含则map插入,然后refresh,最后判断有没有超过capacity,超过则del
         */
        if (map.containsKey(key)) {
            Node node = map.get(key);
            node.val = value;
            refresh(node);
        } else {
            Node node = new Node(key, value);
            map.put(key, node);
            refresh(node);
            if (map.size() > capacity) {
                del();
            }
        }
    }

    private void refresh(Node node) {
        /**
         * 双向链表就是 把当前节点的next 指向下一个结点
         * 下一个节点的pre指向当前节点
         */
        // 删除这个node
        node.next.pre = node.pre;
        node.pre.next = node.next;

        //把它加在前面
        node.pre = head;
        head.next.pre = node;
        node.next = head.next;
        head.next = node;
    }

    private void del() {
        Node node = head.pre;
        node.next.pre = node.pre;
        node.pre.next = node.next;
        map.remove(node.key);
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache(2);
        cache.put(1, 1);
        cache.put(2, 2);
        System.out.println(cache.get(1));
        cache.put(3, 3);
        System.out.println(cache.get(2));
        cache.put(4, 4);
        System.out.println(cache.get(1));
        System.out.println(cache.get(3));
        System.out.println(cache.get(4));
    }
}

快排

找到基准值,把小于基准值的放在他前面,大于的放到他后面,同时,序列被划分成两个子序列,再分别对两个子序列进行快速排序,直到子序列的长度为1,则完成排序。

import java.util.*;
public class QuickSort {
    public int[] sortArray(int[] nums){
        quickSort(nums, 0, nums.length -1);
        return nums;
    }

    public void quickSort(int[] nums, int left, int right) {
        if(nums == null)
            return;
        if(left >= right)
            return;

        int i = left;
        int j = right;
        int temp = nums[i];
        while(i < j){
            while(i < j && temp <= nums[j]){
                j--;
            }
            nums[i] = nums[j];

            while (i < j && temp >= nums[i]) {
                i++;
            }
            nums[j] = nums[i];
            nums[i] = temp;
        }

        quickSort(nums,left,i-1);
        quickSort(nums,i+1,right);
    }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        String[] num = sc.nextLine().split(" ");
        int[] nums = new int[num.length];
        for(int i = 0; i < num.length;i++){
            nums[i] = Integer.valueOf(num[i]);
        }

        QuickSort test = new QuickSort();
        int[] res = test.sortArray(nums);
        for(int i: res){
            System.out.print(i+" ");
        }
    }
}

数组

1299. 将每个元素替换为右侧最大元素

题目
思路:
逆序解决,而且不能用多余的空间,
arr[i] = max(arr[i+1],res[i+1])

import java.util.Map;
import java.util.Scanner;

public class Solution {

    public int[] replaceElements(int[] arr){
        int cur_max = arr[arr.length-1];
        arr[arr.length-1] = -1;

        for(int i = arr.length-2;i >=0;i--){
            int tmp = arr[i];
            arr[i] = Math.max(cur_max,arr[i+1]);
            cur_max = tmp;
        }
        return arr;
    }

    public static void main(String[] args){
        Solution test = new Solution();

        Scanner sc = new Scanner(System.in);
        String[] nums = null;
        nums = sc.nextLine().split(" ");
        int[] arr = new int[nums.length];
        for(int i = 0;i < nums.length;i++){
            arr[i] = Integer.valueOf(nums[i]);
        }

        int[] res = test.replaceElements(arr);
        for(int i:res){
            System.out.print(i+" ");
        }
    }
}

42.接雨水

题目
思路:
记录该位置左边的最大值和右边的最大值,然后该位置接水量就是Math.min(right[i],left[i]) - height[i]

import java.util.Scanner;

public class Solution {
    public int trap(int[] height){

        if (height.length < 3){
            return 0;
        }

        int[] right = new int[height.length];
        int[] left = new int[height.length];

        left[0] =  height[0];
        right[height.length - 1] = height[height.length - 1];

        for(int i = 1;i<height.length;i++){
            left[i] = Math.max(height[i],left[i-1]);
        }

        for(int i = height.length - 2 ;i >= 0;i--){
            right[i] = Math.max(height[i],right[i+1]);
        }

        int res = 0;
        for(int i = 0;i < height.length;i++){
            res += Math.min(right[i],left[i]) - height[i];
        }

        return res;
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] nums = null;
        nums = sc.nextLine().split(" ");
        int[] height = new int[nums.length];
        for(int i=0;i<nums.length;i++){
            height[i] = Integer.valueOf(nums[i]);
        }

        Solution test = new Solution();
        System.out.println(test.trap(height));
    }
}

单调栈

84.柱状图中最大的矩形

当找到比栈顶元素小的时候,就把栈顶元素弹出,计算area。

package Array;

import util.ArrayInputUtil;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * 84.柱状图最大的矩形
 * [0,9]出错
 */

public class LargestRectangleArea {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        if (len == 0) {
            return 0;
        }

        if (len == 1) {
            return heights[0];
        }
        int[] newHeights = new int[len + 2];
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i < len; i++) {
            newHeights[i + 1] = heights[i];
        }
        heights = newHeights;
        stack.add(0);
        int area = 0;
        for (int i = 1; i < heights.length; i++) {
            while (heights[i] < heights[stack.peekLast()]) {
                int height = heights[stack.removeLast()];
                int width = i - stack.peekLast() - 1;
                area = Math.max(area,height * width);
            }
            stack.add(i);
        }
        return area;
    }

    public static void main(String[] args) {
//        int[] height = ArrayInputUtil.arrayInput();
        int[] height = {2,1,5,6,2,3};
        LargestRectangleArea test = new LargestRectangleArea();
        System.out.println(test.largestRectangleArea(height));
    }
}

739.每日温度

题目
思路:
简历一个从栈顶到栈底递增的栈,当当前元素大于栈顶,即可出栈,记录过了多少天,否则出栈。

package monotonousStack;

import java.util.ArrayDeque;
import java.util.Deque;

public class DailyTemperatures {

    public int[] dailyTemperatures(int[] T) {
        int len = T.length;
        int[] res = new int[len];
        if (len == 0 || len == 1) {
            return res;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        stack.add(0);
        for(int i = 1;i < T.length;i++){
            while(!stack.isEmpty() && T[i] > T[stack.peekLast()]){
                int j = stack.removeLast();
                res[j] = i - j;
            }
            stack.add(i);
        }
        return res;
    }

    public static void main(String[] args) {
        int[] T = {73, 74, 75, 71, 69, 72, 76, 73};
        DailyTemperatures test = new DailyTemperatures();
        int[] res = test.dailyTemperatures(T);
        for (int i = 0; i < res.length; i++) {
            System.out.print(res[i] + " ");
        }
    }
}

503.下一个更大元素II

题目
思路:
建立一个单调递增的栈,如果当前元素大于就出栈,并记录,注意是循环数组,所以需要第二个for循环处理一次。

package monotonousStack;

import java.util.*;

/**
 * 503.下一个最大元素
 * [5,4,3,2,1]出错
 */
public class NextGreaterElements {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        if (nums.length == 0) {
            return res;
        }
        if (nums.length == 1) {
            res[0] = -1;
            return res;
        }
        Arrays.fill(res, -1);
        Deque<Integer> stack = new ArrayDeque<>();
        stack.add(0);
        for (int i = 1; i < nums.length; i++) {
            while (!stack.isEmpty() && nums[i] > nums[stack.peekLast()]) {
                int j = stack.removeLast();
                res[j] = nums[i];
            }
            stack.add(i);
        }
        for (int i = 0; i < nums.length - 1; i++) {
            while (!stack.isEmpty() && nums[i] > nums[stack.peekLast()]) {
                int j = stack.removeLast();
                res[j] = nums[i];
            }
            stack.add(i);
        }
        return res;
    }

    public static void main(String[] args) {
        int[] nums = {5,4,3,2,1};
        NextGreaterElements test = new NextGreaterElements();
        int[] res = test.nextGreaterElements(nums);
        for (int i = 0; i < res.length; i++) {
            System.out.print(res[i] + " ");
        }
    }
}

双指针

三数之和

题目
思路:
排序后,用双指针
注意:
1、排除重复答案的

            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }

2、判断tmp==0后不能直接left++ right–

                     while(left < right && nums[left] == nums[left+1]){
                        left += 1;
                    }

                    while(left < right && nums[right] == nums[right - 1]){
                        right -= 1;
                    }
import java.lang.reflect.Array;
import java.util.*;

public class Solution {
    public List<List<Integer>> threeSum(int[] nums){
        List<List<Integer>> res = new ArrayList<List<Integer>>();

        if(nums.length < 3){
            return res;
        }

        Arrays.sort(nums);

        for(int i = 0;i<nums.length-2;i++){

            // 处理 答案重复
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }

            int left = i + 1;
            int right = nums.length - 1;
            while(left < right){
                int tmp = nums[i] + nums[left] + nums[right];
                if (tmp == 0){
                    List<Integer> cur = new ArrayList<>();
                    cur.add(nums[i]);
                    cur.add(nums[left]);
                    cur.add(nums[right]);
                    res.add(cur);

                    while(left < right && nums[left] == nums[left+1]){
                        left += 1;
                    }

                    while(left < right && nums[right] == nums[right - 1]){
                        right -= 1;
                    }

                    left += 1;
                    right -=1;
                }

                else if(tmp > 0){
                    right -= 1;
                }
                else{
                    left += 1;
                }
            }
        }
        return res;
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] arr = null;
        arr = sc.nextLine().split(" ");
        int[] nums = new int[arr.length];
        for(int i = 0;i < arr.length;i++){
            nums[i] = Integer.valueOf(arr[i]);
        }

        Solution test = new Solution();
        System.out.println(test.threeSum(nums));
    }
}

滑动窗口

3. 无重复字符的最长子串

题目
思路:
极端例子 “abcbfa”
用一个map记录s[i]及其索引位置,map(s[i],index)
用start和end来记录窗口,当出现s[i]在map时,则将start更新到index + 1,然后更新index,当出现s[i]在map时,但是index<start说明窗口不包括了,即忽略掉;

java实现

import java.util.*;

public class LengthOfLongestSubString {
    public int lengthOfLongestSubString(String s) {
        if (s.length() == 0) {
            return 0;
        }
        Map<Character, Integer> map = new HashMap<>();
        int res = 0;
        int start = 0;
        int end = 0;
        for(int i = 0;i < s.length();i++) {
            char c = s.charAt(i);
            if(!map.containsKey(c) || map.get(c) < start){
                map.put(c,i);
                end = i;
                res = Math.max(res, end - start + 1);
            }
            else{
                start = map.get(c) + 1;
                map.put(c,i);
                end = i;
                res = Math.max(res, end - start + 1);
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        LengthOfLongestSubString test = new LengthOfLongestSubString();
        System.out.println(test.lengthOfLongestSubString(s));
    }
}

python实现

# -*- coding: utf-8 -*-
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        if not s:
            return 0
        
        s_dict = {}
        start = 0
        res = 0
        for i in range(len(s)):
            if s[i] not in s_dict.keys() or s_dict[s[i]] < start:
                s_dict[s[i]] = i
                end = i
                res = max(res, end - start + 1)
            else:
                start = s_dict[s[i]] + 1
                s_dict[s[i]] = i
                end = i
                res = max(res, end - start + 1)
        return res
if __name__ == "__main__":
    s = input()
    test = Solution()
    print(test.lengthOfLongestSubstring(s))

1004.最大连续1的个数III

题目
最大窗口随着满足条件而增大,假如不满足条件就保持原来大小往右滑
参考:https://www.bilibili.com/video/BV1Sb411v7qp?from=search&seid=7404090548336897110

# -*- coding: utf-8 -*-
class Solution(object):
    def problem(self,A,K):
        l = 0
        for r in range(len(A)):
            if A[r] == 0:
                K -= 1
            if K < 0:
                if A[l] == 0:
                    K += 1
                l += 1
        return r - l + 1

if __name__ == '__main__':
    K = int(input())
    A = list(map(int,input().split()))
    test = Solution()
    print(test.problem(A,K))

424.替换后的最长重复子串

题目
思路:
记录窗口内字符的数量,并记录这些字符中出现的最大次数
假如当前窗口- 最大次数大于k,说明这个窗口是替换完都不行的,因此左指针后移,并吧窗口内的字符次数-1

import java.util.*;

public class CharacterReplacement {
    public int characterReplacement(String s, int k) {
        char[] chars = new char[26];
        int historyMaxlen = 0;
        int res = 0;
        int l = 0;
        for (int r = 0; r < s.length(); r++) {
            char c = s.charAt(r);
            chars[c - 'A']++;
            historyMaxlen = Math.max(historyMaxlen, chars[c - 'A']);
            if (r - l + 1 - historyMaxlen > k) {
                char lc = s.charAt(l);
                chars[lc - 'A']--;
                l++;
            }
            res = Math.max(res, r - l + 1);
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        int k = sc.nextInt();
        CharacterReplacement test = new CharacterReplacement();
        System.out.println(test.characterReplacement(s, k));
    }
}

# -*- coding: utf-8 -*-
class Solution(object):
    def problem(self,s,k):
        l = 0
        res = 0
        char = [0] * 26
        ## 用historyMax替换掉max(char)
        historyMax = 0
        for r in range(len(s)):
            char[ord(s[r]) - ord('A')] += 1
            historyMax = max(historyMax,char[ord(s[r]) - ord('A')])
            if r - l + 1 - historyMax > k:
                char[ord(s[l]) - ord('A')] -= 1
                l += 1

            res = max(res, r - l + 1)
        return res

if __name__ == '__main__':

    s = input()
    k = int(input())
    test = Solution()
    print(test.problem(s,k))

动态规划

120.三角形最小路径和

题目
思路:
自底向上:
triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1])

# -*- coding: utf-8 -*-
class Solution(object):
    def problem(self, triangle):
        n = len(triangle)
        for i in range(n-2,-1,-1):
            for j in range(i+1):
                triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1])
        return triangle[0][0]

if __name__ == '__main__':

    nums = []
    n = int(input())
    for i in range(n):
        l = list(map(int, input().split()))
        nums.append(l)

    test = Solution()
    print(test.problem(nums))

最大子序列和

题目
思路:
假如当前的curMax < 0,curMax要重新计,curMax = nums[i],否则相加起来跟res比较

import java.util.*;
public class MaxSubArray {
    public int maxSubArray(int[] nums) {

        int curMax = nums[0];
        int res = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (curMax < 0) {
                curMax = nums[i];
            } else {
                curMax += nums[i];
            }
            if (curMax > res) {
                res = curMax;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] stringArray = sc.nextLine().split(" ");
        int[] nums = new int[stringArray.length];
        for (int i = 0; i < stringArray.length; i++) {
            nums[i] = Integer.valueOf(stringArray[i]);
        }

        MaxSubArray test = new MaxSubArray();
        System.out.println(test.maxSubArray(nums));
    }
}

121.买卖股票I

题目
思路:
前后做差,求最大的子序列和。

package dp;

public class MaxProfit {
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len <= 1) {
            return 0;
        }
        int[] nums = new int[len - 1];
        for(int i = 1; i<len;i++){
            nums[i-1] = prices[i] - prices[i-1];
        }
        int res = maxSubArray(nums);
        return res > 0 ? res: 0;
    }

    public int maxSubArray(int[] nums) {

        int curSum = nums[0];
        int maxSum = nums[0];
        for(int i = 1;i<nums.length;i++){
            if(curSum > 0){
                curSum += nums[i];
            }
            else{
                curSum = nums[i];
            }

            if(curSum > maxSum){
                maxSum = curSum;
            }
        }

        return maxSum;
    }

    public static void main(String[] args) {
        int[] prices = {7, 1, 5, 3, 6, 4};
        MaxProfit test = new MaxProfit();
        System.out.println(test.maxProfit(prices));
    }
}

另外一个思路:
记录当前最小的数值,做差更新maxprofit

class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        min_val = sys.maxsize
        max_profit = 0
        for i in prices:

            if i < min_val:
                min_val = i

            else:
                if max_profit < i - min_val:
                    max_profit = i - min_val

        return max_profit

122.买卖股票II

题目
思路:
直接前后想减,把差值大于零相加起来。

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        res = 0
        for i in range(1,len(prices)):
            if prices[i] - prices[i-1] > 0:
                res += prices[i] - prices[i-1]
        return res

221.最大正方形

题目
思路:
注意边界判断,
matrix[i][j] == '1’的时候,才进行dp[i][j] = min(dp[i-1][j-1],[i-1][j],[i][j-1]) + 1

import java.util.*;

public class MaximalSquare {
    public int maximalSquare(char[][] matrix) {
        int maxLen = 0;
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return maxLen;
        }
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i - 1][j - 1]), dp[i][j - 1]) + 1;
                    }
                    maxLen = Math.max(dp[i][j], maxLen);
                }
            }
        }
        return maxLen * maxLen;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int row = sc.nextInt();
        int col = sc.nextInt();
        char[][] maxtrix = new char[row][col];
        for (int r = 0; r < row; r++) {
            for (int c = 0; c < col; c++) {
            //输入字符
                maxtrix[r][c] = sc.next().charAt(0);
            }
        }

        MaximalSquare test = new MaximalSquare();
        System.out.println(test.maximalSquare(maxtrix));
    }
}

516.最长回文子序列

题目
思路:
用dp[i][j] 表示i和j最长的回文子序列
i从0向右遍历,j从i-1向左遍历
如果i和j的字符相等,那么相当于dp[i][j] = dp[i - 1][j + 1] + 2;
如果不等,则:dp[i][j] = Math.max(dp[i - 1][j], dp[i][j + 1]);

package dp;

import java.util.Scanner;

/**
 * 516,最长回文子序列
 */
public class LongestPalindromeSubseq {
    public int longestPalindromeSubseq(String s) {

        int n = s.length();
        int[][] dp = new int[n][n];

        for (int i = 0; i < n; i++) {
            dp[i][i] = 1;
            for (int j = i - 1; j >= 0; j--) {
                if (s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i - 1][j + 1] + 2;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j + 1]);
                }
            }
        }
        return dp[n - 1][0];
    }

    public static void main(String[] args) {
        LongestPalindromeSubseq test = new LongestPalindromeSubseq();
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        System.out.println(test.longestPalindromeSubseq(s));
    }
}

链表

206.反转链表

public class Solution {
    public ListNode reverseList(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(head != null){
            cur = head;
            head = head.next;    //注意把提前这一行放这里
            cur.next = pre;
            pre = cur;
        }
        return cur;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next =  new ListNode(5);

        Solution test = new Solution();
        ListNode res = test.reverseList(head);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }
    }
}

反转链表2

题目
思路
第一步:找到待反转节点的前一个节点。记录为beforInverNode,并记录开始反转的节点startInverNode
第二步:反转m到n这部分。
第三步:将反转的起点的next指向反转的后面一部分。
第四部:将startInverNode的next指向后面不需要反转的部分
注意反转完后链表的状态:
在这里插入图片描述
所以需要:

        beforeInverseNode.next = pre;
        startInverseNode.next = node;
import java.util.List;

public class Solution {
    public ListNode reverseBetween(ListNode head,int m,int n){
        int i = 0;
        ListNode pHead = new ListNode(0);
        pHead.next = head;
        head = pHead;
        ListNode start = null;
        ListNode end = null;
        ListNode pEnd = null;
        while (head != null) {
            if (i == m - 1) {
                pEnd = head;
                start = head.next;
            }

            if (n == i) {
                end = head;
                ListNode tmp = head.next;
                end.next = null;
                HashMap<String, ListNode> map = reverseList(start);
                ListNode reverseHead = map.get("head");
                ListNode reverseTail = map.get("tail");
                pEnd.next = reverseHead;
                reverseTail.next = tmp;
                head = reverseTail;
            }
            head = head.next;
            i++;
        }
        return pHead.next;
    }

    public static void main(String[] args) {

        int m = 2, n = 6;
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next =  new ListNode(3);
        head.next.next.next =  new ListNode(4);
        head.next.next.next.next =  new ListNode(5);
        head.next.next.next.next.next =  new ListNode(6);
        head.next.next.next.next.next.next =  new ListNode(7);

        Solution test = new Solution();
        ListNode res = test.reverseBetween(head,m,n);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }
    }
}

k个一组翻转链表

题目

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode pHead = new ListNode(0);
        pHead.next = head;
        ListNode pEnd = pHead;
        ListNode start = head;
        int i = 0;
        while (head != null) {
            i++;
            if (i == k) {
                ListNode nextstart = head.next;
                ListNode end = head;
                end.next = null;
                HashMap<String,ListNode> map = reverseList(start);
                pEnd.next = map.get("head");
                head = map.get("tail");
                head.next = nextstart;
                pEnd = head;
                start = nextstart;
                i = 0;
            }
            head = head.next;
        }
        return pHead.next;
    }

    public HashMap<String, ListNode> reverseList(ListNode head) {
        HashMap<String, ListNode> map = new HashMap<>();
        map.put("tail", head);
        ListNode pre = null;
        ListNode cur = head;
        while (head != null) {
            cur = head;
            head = head.next;
            cur.next = pre;
            pre = cur;
        }
        map.put("head", cur);
        return map;
    }
}

21.合并两个有序链表

题目
递归

public class Solution {
    public ListNode mergeTwoLists(ListNode l1,ListNode l2){
        if(l1 == null){
            return l2;
        }

        else if(l2 == null){
            return l1;
        }

        else if(l1.val < l2.val){
            l1.next = mergeTwoLists(l1.next,l2);
            return l1;
        }

        else{
            l2.next = mergeTwoLists(l1,l2.next);
            return l2;
        }

    }

    public static void main(String[] args) {
        ListNode l1 = new ListNode(1);
        l1.next = new ListNode(2);
        l1.next.next =  new ListNode(4);

        ListNode l2 = new ListNode(1);
        l2.next = new ListNode(3);
        l2.next.next =  new ListNode(4);

        Solution test = new Solution();
        ListNode res = test.mergeTwoLists(l1,l2);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }
    }
}

23.合并k个排序链表

题目
思路:
分治,两两合并
在这里插入图片描述

public class Solution {
    public ListNode mergeKlists(ListNode[] lists){
        int interval = 1;
        int len = lists.length;
        while(len > interval){
            for(int i = 0;i < len - interval; i += interval * 2){
                lists[i] = merge2lists(lists[i], lists[i + interval]);
            }
            interval *= 2;
        }
        return len > 0 ? lists[0]:null;
    }

    public ListNode merge2lists(ListNode l1,ListNode l2){

        if(l1 == null){
            return l2;
        }

        else if(l2 == null){
            return l1;
        }

        else if(l1.val < l2.val){
            l1.next = merge2lists(l1.next,l2);
            return l1;
        }

        else{
            l2.next = merge2lists(l1,l2.next);
            return l2;
        }
    }

    public static void main(String[] args) {
//        ListNode l1 = new ListNode(1);
//        l1.next = new ListNode(4);
//        l1.next.next =  new ListNode(5);
//
//        ListNode l2 = new ListNode(1);
//        l2.next = new ListNode(3);
//        l2.next.next =  new ListNode(4);
//
//        ListNode l3 = new ListNode(2);
//        l3.next = new ListNode(6);

//        ListNode[] lists = {l1,l2,l3};
        ListNode[] lists = {};

        Solution test = new Solution();
        ListNode res = test.mergeKlists(lists);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }
    }
}

141.环形链表

题目

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while(head!=null){
            if(set.contains(head)){
                return true;
            }
            else{
                set.add(head);
            }
            head = head.next;
        }
        return false;
    }
}

142.环形链表ii

题目
思路:
快慢指针
在这里插入图片描述

import java.util.HashSet;
import java.util.Set;

public class Solution {

    public ListNode detectCycle(ListNode head){

        ListNode fast = head;
        ListNode slow = head;

        while(fast != null && fast.next!= null){
            fast = fast.next.next;
            slow = slow.next;

            if(fast == slow){
                fast = head;
                while (fast != slow){
                    fast = fast.next;
                    slow = slow.next;
                }
                return fast;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(3);
        ListNode node = new ListNode(2);
        head.next = node;
        head.next.next = new ListNode(0);
        head.next.next.next = new ListNode(-4);

        head.next.next.next.next = node;

        Solution test = new Solution();
        ListNode res = test.detectCycle(head);

        System.out.println(res.val);

    }
}

83.删除排序链表中的重复元素

题目

public class Solution {
    public ListNode deleteDuplicates(ListNode head){
        if(head == null){
            return null;
        }
        ListNode cur = head;
        while(head.next != null){
            if(head.val != head.next.val){
                head = head.next;
            }
            else{
                //这一步很关键
                head.next = head.next.next;
            }
        }
        return cur;
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(1);
        head.next.next =  new ListNode(2);
        head.next.next.next =  new ListNode(3);
        head.next.next.next.next =  new ListNode(3);

        Solution test = new Solution();
        ListNode res = test.deleteDuplicates(head);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }

    }
}

倒数第k个节点

题目
思路:快指针先走k步

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode fast = head;
        int i = 0;
        while(fast != null && i < k){
            fast = fast.next;
            i++;
        }

        ListNode slow = head;
        if(i == k){

            while(fast != null){
                fast = fast.next;
                slow = slow.next;
            }

            return slow;
        }

        return null;
    }
}

19.删除链表的倒数第N个节点

题目

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {

        ListNode fast = head;
        int i = 0;
        while(fast != null && i < n){
            fast = fast.next;
            i++;
        }
        //防止[1] n = 1和[1,2] n = 2 
        if(fast == null){
            head = head.next;
            return head;
        }

        if(i == n){
            ListNode pre = new ListNode(0);
            pre.next = head;
            ListNode slow = head;
            while(fast != null){
                fast = fast.next;
                head = slow;
                slow = slow.next;
            }

            head.next = slow.next;
            return pre.next;
        }
        return null;
    }

    public static void main(String[] args) {

        int n = 2;
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next =  new ListNode(3);
//        head.next.next.next =  new ListNode(4);
//        head.next.next.next.next =  new ListNode(5);
//        head.next.next.next.next.next =  new ListNode(6);
//        head.next.next.next.next.next.next =  new ListNode(7);

        Solution test = new Solution();
        ListNode res = test.removeNthFromEnd(head,n);
        while(res != null){
            System.out.print(res.val + " ");
            res = res.next;
        }

    }
}

二叉树

144.二叉树的前序遍历

import java.util.ArrayList;
import java.util.List;
public class Solution {
    List<Integer> res = new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root){
        if(root != null){
            res.add(root.val);
            preorderTraversal(root.left);
            preorderTraversal(root.right);
        }
        return res;
    }
    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.right = new TreeNode(2);
        root.right.left = new TreeNode(3);

        Solution test = new Solution();
        System.out.println(test.preorderTraversal(root));
    }
}

102.二叉树的层序遍历

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class TreeLevelOrder {
    /**
     * 102.二叉树的层序遍历
     */
    public List<List<Integer>> levelOrder(TreeNode root){

        List<List<Integer>> res = new ArrayList<>();
        if(root == null){
            return res;
        }

        List<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(queue.size() > 0){
            int len = queue.size();
            List<Integer> cur = new ArrayList<>();
            for(int i = 0;i < len;i++){
                TreeNode curNode = queue.remove(0);
                cur.add(curNode.val);

                if(curNode.left != null){
                    queue.add(curNode.left);
                }

                if(curNode.right != null){
                    queue.add(curNode.right);
                }
            }

            res.add(cur);
        }
        return res;
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(3);
        root.left = new TreeNode(9);
        root.right = new TreeNode(20);

        root.right.left = new TreeNode(15);
        root.right.right = new TreeNode(7);

        TreeLevelOrder test = new TreeLevelOrder();
        System.out.println(test.levelOrder(root));
    }
}

回溯

77.组合

题目

package backtracking;

import java.util.*;

public class Combine {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> res = new ArrayList<>();
        if (k <= 0 || n < k) {
            return res;
        }
        Deque<Integer> path = new ArrayDeque<>();
        dfs(n, k, 1, res, path);
        return res;
    }

    public void dfs(int n, int k, int begin, List<List<Integer>> res, Deque<Integer> path) {

        if (path.size() == k) {
            res.add(new ArrayList<>(path));
//            System.out.println("res => " + res);
            return;
        }
        // 只有这里 i <= n - (k - path.size()) + 1
        for (int i = begin; i <= n - (k - path.size()) + 1; i++) {
            path.add(i);
//            System.out.println("递归之前 => " + path);
            dfs(n, k, i + 1, res, path);
//            System.out.println("递归之后 => " + path);
            path.removeLast();
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
//        int n = sc.nextInt();
//        int k = sc.nextInt();
        int n = 4;
        int k = 3;
        Combine test = new Combine();
        System.out.println(test.combine(n, k));
    }
}

470.用Rand7()实现Rand10()

题目
参考题解

已知 rand_N() 可以等概率的生成[1, N]范围的随机数
那么:
(rand_X() - 1) × Y + rand_Y() ==> 可以等概率的生成[1, X * Y]范围的随机数
即实现了 rand_XY()
7 * 7 = 49 ,小于40取模10

/**
 * The rand7() API is already defined in the parent class SolBase.
 * public int rand7();
 * @return a random integer in the range 1 to 7
 */
class Solution extends SolBase {
    public int rand10() {
        while(true){
            int x = (rand7() - 1) * 7 + rand7();
            if(x <= 40){
                return x % 10 + 1;
            }
        }
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值