算法分类汇总

数位 DP - OI Wiki

按照大纲把下面的题目刷完,并把代码烂熟于心,就几乎可以应对 90% 的面试算法考题了。

本篇内容包括如下模块:

  • 高频算法题系列:链表

  • 【】【有真题】高频算法题系列:字符串

  • 【】【有真题】高频算法题系列:数组问题

  • 高频算法题系列:二叉树

  • 【】高频算法题系列:排序算法

  • 【】高频算法题系列:二分查找

  • 【】高频算法题系列:动态规划

  • 高频算法题系列:BFS

  • 【】高频算法题系列:栈

  • 【】高频算法题系列:DFS

  • 【】高频算法题系列:回溯算法

其中标的部分代表非常高频的考题,其中不乏笔者遇到的原题。其中对于每一类,首先会列出包含的考题,然后针对每一道考题会给出难度、考察知识点、是否是面试真题,在每道题详细介绍时,还会给出每道题的 LeetCode 链接,帮助读者理解题意,以及能够进行实际的测验,还可以观看其他人的答案,更好的帮助准备。

高频算法题系列:链表

笔者遇到的高频链表题主要包含这几道:

  • 通过快慢指针寻找链表中点 【简单】

  • 通过链表的后续遍历判断回文链表问题 【简单】

  • 链表的反向输出 【简单】

  • 合并 K 个升序链表 【困难】

  • K个一组翻转链表 【困难】

  • 环形链表 【简单】

  • 排序链表 【中等】

  • 相交链表 【简单】

寻找链表中点

题解

通过快慢指针寻找链表中点

/**
  *
  */
function findCenter(head) {
    let slower = head, faster = head;
    while (faster && faster.next != null) {
        slower = slower.next;
        faster = faster.next.next;
    }
    // 如果 faster 不等于 null,说明是奇数个,slower 再移动一格
    if (faster != null) {
        slower = slower.next;
    }
    return slower;
}

前序遍历判断回文链表

 【LeetCode 直通车】:234 回文链表(简单)[1]

题解1

利用链表的后续遍历,使用函数调用栈作为后序遍历栈,来判断是否回文

class Solution {
//方法2,倒叙遍历链表和正顺遍历链表
ListNode left;
boolean isPalindrome=true;
 public boolean isPalindrome(ListNode head) {
     this.left=head;
     isPalindromeDFS(head);
    return this.isPalindrome;

 }
  public void isPalindromeDFS(ListNode right){
      if(right==null){
          return;
      }
      isPalindromeDFS(right.next);
      if(right.val!=this.left.val){
          this.isPalindrome=false;
          return;
      }
      if(this.left!=null){
          this.left=this.left.next;
      }
    
  }


//    public boolean isPalindrome(ListNode head) {
// 		  ListNode fast=head,slow=head;
// 		  while(fast!=null&&fast.next!=null){
// 			  slow=slow.next;
// 			  fast=fast.next.next;
// 		  }
// 		  ListNode  lastNodes=null;
// 		  if(fast==null){
// 			    lastNodes=reverseNode2(slow);
// 		  }else{
// 			    lastNodes=reverseNode2(slow.next);
// 		  }
// 		  while(lastNodes!=null){
// 			  if(head.val!=lastNodes.val){
// 				  return false;
// 			  }
// 			  head=head.next;
// 			  lastNodes=lastNodes.next;
			  
// 		  }
// 		return true;
// 	    }
// 	  public static  ListNode reverseNode2(ListNode head){
//            if(head==null){
// 			  return null;
// 		  }
// 		  if(head.next==null){
// 			  return head;
// 		  }
// 		  ListNode next=head.next;
// 		  ListNode node=reverseNode2(next);
// 		  next.next=head;
// 		  head.next=null;
// 		  return node;
		  
// 	  }
	
}

反转链表

 【LeetCode 直通车】:206 反转链表(简单)[2]

题解

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    if (head == null || head.next == null) return head;
    let last = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return last;
};

方法2
 public ListNode reverseList(ListNode head) {
        if(head==null){
            return null;
        }
        ListNode pre=null,cur=head,next=head.next;
        while(cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
 }

合并K个升序链表

 【LeetCode 直通车】:23 合并K个升序链表(困难)[3]

347. 前 K 个高频元素

题解

public ListNode mergeKLists(ListNode[] lists) {
	
	PriorityQueue pr=new PriorityQueue(new Comparator(){
        public int compare(ListNode o1,ListNode o2){
            return o1.val-o2.val;
        }
    });
	ListNode head=new ListNode();
	ListNode tail =head;
	if(lists==null||lists.length==0){
		return head.next;
	}
	for(ListNode temp:lists){
		if(temp!=null){
			pr.add(temp);
		}
		
	}
	
	while(!pr.isEmpty()){
		ListNode tempNode=pr.poll();
		tail.next=tempNode;
		tail =tail.next;
		if(tempNode.next!=null)
		pr.offer(tempNode.next);
		
	}
	return head.next;
	
}

92. 反转链表 II

class Solution {
public ListNode nextNewNode=null;
 public ListNode reverseBetween(ListNode head, int left, int right) {
        if(head==null){
            return null;
        }
        if(right==0){
            return head;
        }
        if(left==1){
            return reverseNodesK(head,right);
        }else{
            head.next=reverseBetween(head.next,left-1,right-1);
            return head;
        }
 }
    ListNode reverseNodesK(ListNode head,int k){
        if(head==null||head.next==null){
            return head;
        }
        if(k==1){
            this.nextNewNode=head.next;
            return head;
        }
        ListNode next=head.next;
        ListNode resultNode=reverseNodesK(next,k-1);
        next.next=head;
        head.next=nextNewNode;
        return resultNode;
    }
 
}

K 个一组翻转链表

 【LeetCode 直通车】:25 K 个一组翻转链表(困难)[4]

题解

/**
 * Definition for singly-linked list.
 * public 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 Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null||k==0){
            return head;
        }
        ListNode tail =head;
        for(int i=0;i

环形链表

 【LeetCode 直通车】:141 环形链表(简单)[5]

题解

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    if (head == null || head.next == null) return false;
    let slower = head, faster = head;
    while (faster != null && faster.next != null) {
        slower = slower.next;
        faster = faster.next.next;
        if (slower === faster) return true;
    }
    return false;
};

142. 环形链表 II

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

排序链表

 【LeetCode 直通车】:148 排序链表(中等)[6]

题解

class Solution {
     public ListNode sortList(ListNode head) {
    	if(head==null||head.next==null){
    		return head;
    	}
    	ListNode middleNode=findMiddle(head);
    	ListNode nextList=middleNode.next;
    	middleNode.next=null;
    	ListNode sortedList1=sortList(head);
    	ListNode sortedList2=sortList(nextList);
    	return mergeSortedList(sortedList1,sortedList2);
    	
    	

    }
    public ListNode findMiddle(ListNode head){
    	ListNode faster=head,slower=head;
        if(faster!=null&&faster.next!=null&&faster.next.next==null){
            return faster;
        }
    	while(faster!=null&&faster.next!=null){
    		faster=faster.next.next;
    		slower=slower.next;
    	}
    	return slower;
    }
    
    public ListNode mergeSortedList(ListNode a,ListNode b){
    	ListNode head=new ListNode(0);
    	ListNode tail=head;
    	while(a!=null&&b!=null){
    		if(a.val>b.val){
    			tail.next=b;
    			tail=tail.next;
    			b=b.next;
    		}else{
    			tail.next=a;
    			tail=tail.next;
    			a=a.next;
    		}
    	}
    	if(a==null){
    		tail.next=b;
    	}else{
    		tail.next=a;
    	}
    	return head.next;
    }
    
}

相交链表

 【LeetCode 直通车】:160 相交链表(简单)[7]

题解

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode tempA=headA,tempB=headB;
        int i=0;
        while(tempA!=tempB){
            tempA=tempA.next;
            tempB=tempB.next;
            if(tempA==null){
                tempA=headB;
                i++;
            }
            if(tempB==null){
                tempB=headA;
                i++;
            }
            if(i>=3){
                return null;
            }
        }
        return tempA;
        
    }
}

【】高频算法题系列:字符串

主要有以下几类高频考题:

  • 最长回文子串 【中等】【双指针】【面试真题】

  • 最长公共前缀 【简单】【双指针】

  • 无重复字符的最长子串【中等】【双指针】

  • 最小覆盖子串 【困难】【滑动窗口】【面试真题】

  • 424. 替换后的最长重复字符

【面试真题】最长回文子串【双指针】

 【LeetCode 直通车】:5 最长回文子串(中等)[8]

题解

class Solution {
   	   
	    public String longestPalindrome(String s) {
            int maxLength=0;
	        String longestPalindromeStr="";
			  if(s==null||s.length()==0){
                  return null;
              }
               if(s.length()==1){
                  return s;
              }
              int dp[][]=new int[s.length()][s.length()];
              for(int i=0;i0&&s.charAt(i)==s.charAt(j)){
                               dp[j][i]=dp[j+1][i-1]+2;
                          }
                      }
                      if(dp[j][i]>maxLength){
                          maxLength=dp[j][i];
                          longestPalindromeStr=s.substring(j,i+1);
                      }
                  }

              }
                if(maxLength==0){
                    return s.substring(0,1);
                }

              return longestPalindromeStr;
	    }
	

    //   public int longestPalindrome=0;
    //   public String longestPalindromeStr;
	//   public String longestPalindrome(String s) {
    //       if(s==null||s.length()==0){
    //           return null;
    //       }
    //       for(int i=0;i=0&&start2longestPalindrome){
    //           longestPalindrome=start2-start1;
    //           longestPalindromeStr=s.substring(start1+1,start2);
    //       }

    //   }
	
}

516. 最长回文子序列

class Solution {

    public int longestPalindromeSubseq(String s) {

        int m=s.length();

        int [][]dp=new int[m][m];

        for(int i=0;i

            dp[i][i]=1;

            for(int j=i-1;j>=0;j--){

                if(s.charAt(i)==s.charAt(j)){

                    dp[j][i]=dp[j+1][i-1]+2;

                }else{

                    dp[j][i]=Math.max(dp[j][i-1],dp[j+1][i]);

                }

            }

        }

        return dp[0][m-1];

    }

}

最长公共前缀【双指针】

 【LeetCode 直通车】:14 最长公共前缀(简单)[9]

题解

class Solution {
    public String longestCommonPrefix(String[] strs) {
        String longestCommonPrefix=strs[0];
        for(int i=1;i

无重复字符的最长子串【双指针】

209. 长度最小的子数组

283. 移动零(双指针)

 【LeetCode 直通车】:3 无重复字符的最长子串(中等)[10]

题解

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int left=0,right=0;
        int maxLength=0;
        if(s==null||"".equals(s)){
            return 0;
        }
         if(s.length()==1){
            return 1;
        }
        Set set=new HashSet();
        for( ;right

【面试真题】 最小覆盖子串【滑动窗口】

1052. 爱生气的书店老板

1208. 尽可能使字符串相等

 【LeetCode 直通车】:76 最小覆盖子串(困难)[11]

题解

class Solution {
   public String minWindow(String s, String t) {
       if(s==null||t==null||s.length() mapT=new HashMap();
	   Map mapS=new HashMap();
       for(int i=0;i

【】高频算法题系列:数组问题

主要有几类高频考题:

  • 俄罗斯套娃信封问题【困难】【排序+最长上升子序列】【面试真题】

  • 最长连续递增序列 【简单】【双指针】

  • 最长连续序列【困难】【哈希表】

  • 盛最多水的容器【困难】【面试真题】

  • 寻找两个正序数组的中位数【困难】【双指针】

  • 删除有序数组中的重复项【简单】【快慢指针】

  • 和为K的子数组【中等】【哈希表】

  • nSum 问题【系列】【简单】【哈希表】

  • 接雨水【困难】【暴力+备忘录优化】【面试真题】

  • 跳跃游戏【系列】【中等】【贪心算法】

  • 915. 分割数组

【面试真题】俄罗斯套娃信封问题【排序+最长上升子序列】

 【LeetCode 直通车】:354 俄罗斯套娃信封问题(困难)[12]

题解

class Solution {
    public int maxEnvelopes(int[][] envelopes) {
        Arrays.sort(envelopes,new Comparator(){
            public int compare(int []o1,int[]o2){
                if(o1[0]!=o2[0]){
                    return o1[0]-o2[0];
                }else{
                    return o2[1]-o1[1];
                }
            }
        });
        int []dp=new int [envelopes.length];
        int result=0;
        for(int i=0;ienvelopes[j][1]){
                    dp[i]=Math.max(dp[i],dp[j]+1);
                }
            }
            result=Math.max(result,dp[i]);

        }
        return result;

    }
}

最长连续递增序列【快慢指针】

 【LeetCode 直通车】:674 最长连续递增序列(简单)[13]

题解

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        if(nums==null||nums.length==0){
            return 0;
        }
        int tempResult=1;
        int result=1;
        for(int i=0;inums[i]){
                tempResult++;
            }else{
                tempResult=1;
            }
            result=Math.max(result,tempResult);
        }
        return result;

    }
}

最长连续序列 【哈希表】

 【LeetCode 直通车】:128 最长连续序列(困难)[14]

题解

class Solution {
    public int longestConsecutive(int[] nums) {
        Set set=new HashSet();
       for(int num:nums){
           set.add(num);
       }
        int result=0;
        for(int i=0;i

【面试真题】盛最多水的容器【哈希表】

 【LeetCode 直通车】:11 盛最多水的容器(中等)[15]

题解

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
    let n = height.length;
    let left = 0, right = n - 1;
    let maxOpacity = 0;
    while (left < right) {
        let res = Math.min(height[left], height[right]) * (right - left);
        maxOpacity = Math.max(maxOpacity, res);
        if (height[left] < height[right]) left++
        else right--;
    }
    return maxOpacity;
};

寻找两个正序数组的中位数【双指针】

 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难)[16]

题解

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m=nums1.length,n=num2.length;
        if(m>n){
            int []temp=nums1;
            nums1=nums2;
            nums2=temp;
        }
        m=nums1.length,n=num2.length;
        int totalLfetCount=n-(n-m+1)/2;
        int nums1LeftCount=0;
        int nums2LeftCount=0;
        int left=0;right=m-1;
        while(left<=right){
            int middle=right-(right-left)/2;
            int nums2Right=totalLfetCount-middle-1;
            if(nums1[nums1LeftCount-1]>nums2[nums2LeftCount]){
                right=nums1left-1;
            }else{
                left=nums1left+1;
            }

        }


    }
}

删除有序数组中的重复项【快慢指针】

 【LeetCode 直通车】:26 删除有序数组中的重复项(简单)[17]

题解

class Solution {
    public int removeDuplicates(int[] nums) {
      int slower=0,faster=0;
      while(faster

 【LeetCode 直通车】:695 岛屿的最大面积(中等)[18]

题解

class Solution {
    public int maxAreaOfIsland=0;
    public int tempMaxAreaOfIsland=0;
    public int maxAreaOfIsland(int[][] grid) {
        int m=grid.length;
        int n=grid[0].length;
        boolean [][]used=new boolean[m][n];
        for(int i=0;igrid.length-1||j<0||j>grid[0].length-1){
            return;
        }
        if(used[i][j]||grid[i][j]==0){
            return;
        }
        tempMaxAreaOfIsland++;
        maxAreaOfIsland=Math.max(maxAreaOfIsland,tempMaxAreaOfIsland);
        used[i][j]=true;

        maxAreaOfIslandDFS(grid,i+1,j,used);
        maxAreaOfIslandDFS(grid,i-1,j,used);
        maxAreaOfIslandDFS(grid,i,j-1,used);
        maxAreaOfIslandDFS(grid,i,j+1,used);

    }
}

和为K的子数组【哈希表】

437. 路径总和 III

1248. 统计「优美子数组」

974. 和可被 K 整除的子数组

 【LeetCode 直通车】:560 和为K的子数组(中等)[19]

题解

//所有以nums[i]为结尾的和为k的连续子数组,    j到i的连续子数组和为k,则0到j的和为(0到i的和减去k)
class Solution {
    public int subarraySum(int[] nums, int k) {
        if(nums==null||nums.length==0){
            return 0;
        }
        Map mapResult=new HashMap();
        int temp=0;
        int result=0;
        mapResult.put(0,1);
        for(int i=0;i

nSum问题【哈希表】【系列】

  •  【LeetCode 直通车】:1 两数之和(简单)[20]

  •     public int[] twoSum(int[] nums, int target) {
    		Map map=new HashMap();
            for(int i=0;i
  •  【LeetCode 直通车】:167 两数之和 II - 输入有序数组(简单)[21]

  •     public int[] twoSum(int[] numbers, int target) {
            int left=0,right=numbers.length-1;
            while(lefttarget){
                    right--;
                }else{
                    left++;
                }
            }
            return new int[]{-1,-1};
    
        }
  •  【LeetCode 直通车】:15 三数之和(中等)[22]

  •  【LeetCode 直通车】:18 四数之和(中等)[23]

class Solution {
    public List> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        return nSumDFS(nums,4,0,target);

    }
    public List> nSumDFS(int []nums,int n,int start,int target){
        List>  result=new ArrayList>();
        if(n==2){
            int end=nums.length-1;
            while(starttarget){
                    end--;
                     while(nums[end]==nums[end+1]&&start twoSum=new ArrayList();
                     twoSum.add(nums[start]);
                     twoSum.add(nums[end]);
                     result.add(twoSum);
                     start++;
                     end--;
                    while(start>0&&nums[start]==nums[start-1]&&startstart&&nums[i]==nums[i-1]){
                    continue;
                }
                List> tempResult=nSumDFS(nums,n-1,i+1,target-curNum);
                if(tempResult!=null&&tempResult.size()>0){
                    for(List tempList:tempResult){
                        tempList.add(curNum);
                        result.add(tempList);
                    }
                }
             }

        }
       return result;


    }
}

接雨水【暴力+备忘录优化】

 【LeetCode 直通车】:42 接雨水(困难)[24]

题解

//     1.首先我们需要搞清楚,下标为i的雨水量是由什么决定的.
// 是由i左右两边最大值中较小的那个减去height[i]决定的.例 [0,1,0,2,1,0,1,3,2,1,2,1]中,下标为2的位置 值为0,而它的用水量是由左边的最大值1,右边最大值3 中较小的那个 也就是1减去0得到的。

// 2.本题解的双指针先找到当前维护的左、右最大值中较小的那个,例 当前 i 处左边的最大值如果比右边的小,那么就可以不用考虑 i 处右边最大值的影响了,因为 i 处 右边真正的最大值绝对比左边的最大值要大,在不断遍历时,更新max_l和max_r以及返回值即可。例 [0,1,0,2,1,0,1,3,2,1,2,1]中i=2时,值为0,此时max_l一定为1,当前max_r如果为2,即便max_r不是真正的i右边的最大值,也可忽略右边最大值的影响,因为右边真正的最大值一定比左边真正的最大值大。


   public int trap(int[] height) {
		 if(height==null||height.length==0){
			 return 0;
		 }
		 int result=0,left=0,right=height.length-1,leftMax=0,rightMax=0;
		 while(left stack=new Stack();
        int result=0;
        for(int i=0;iheight[stack.peek()]){
                    int heightLow=height[stack.pop()];
                    if(stack.isEmpty()){
                        break;
                    }
                    int deep=Math.min(height[stack.peek()],height[i])-heightLow;
                    result+=(deep*(i-stack.peek()-1)); //此处必须是stack中最后一个值,不能上上一个弹出的,例如  0的时候,7和2之间的宽度,2的时候7和4之间的宽度  [4,2,0,7]

                }
                stack.push(i);
            }
        }
        return result;
      

    }

跳跃游戏【贪心算法】【系列】

  •  【LeetCode 直通车】:55 跳跃游戏(中等)[25]

  • class Solution {
        // 这样以来,我们依次遍历数组中的每一个位置,并实时维护 最远可以到达的位置。对于当前遍历到的位置 xx,如果它在 最远可以到达的位置 的范围内,那么我们就可以从起点通过若干次跳跃到达该位置,因此我们可以用 x + \textit{nums}[x]x+nums[x] 更新 最远可以到达的位置。
        public boolean canJump(int[] nums) { 
    		if(nums==null||nums.length==0){
                return true;
            }
            int rightMost=nums[0];
            for(int i=1;i=nums.length-1;
    	}
    	 
    
    
        //暴力破解法
       	// public boolean canJump;
    	//  public boolean canJump(int[] nums) {
    	// 	 if(nums==null||nums.length==0){
    	// 		 return false;
    	// 	 }
    	// 	 canJumpDFS(nums,0);
    	// 	 return canJump;
    	//     }
    	 
    	 
    	//  public void canJumpDFS(int[] nums,int start){
    	// 	 if(canJump==true){
    	// 		 return;
    	// 	 }
    	// 	 if(start>=nums.length-1){
    	// 		 canJump=true;
    	// 		 return;
    	// 	 }
    	// 	 for(int i=start+1;i<=start+nums[start];i++){
    	// 		 canJumpDFS(nums, i);
    	// 	 }
    		 
    	//  }
    	
    }
  •  【LeetCode 直通车】:45 跳跃游戏 II(中等)[26]

受限于篇幅,这里只给出第一道题的代码模板,也是一面常考真题。

题解

class Solution {
    public int jump(int[] nums) {
       if(nums==null||nums.length<=1){
           return 0;
       }
       int end=nums[0],farthest=nums[0],step=1;
       for(int i=0;i

高频算法题系列:二叉树

主要有以下几类高频考题:

  • 二叉树的最近公共祖先【简单】【二叉树】

  • 二叉搜索树中的搜索【简单】【二叉树】

  • 删除二叉搜索树中的节点【中等】【二叉树】

  • 完全二叉树的节点个数【中等】【二叉树】

  • 二叉树的锯齿形层序遍历【中等】【二叉树】

二叉树的最近公共祖先【二叉树】

 【LeetCode 直通车】:236 二叉树的最近公共祖先(简单)[27]

题解

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
TreeNode result;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    lowestCommonAncestorDFS(root,p,q);
    return result;

}
public boolean lowestCommonAncestorDFS(TreeNode root ,TreeNode p,TreeNode q){
    if(root==null){
        return false;
    }
    boolean inCurren=false;
    if(root.val==p.val||root.val==q.val){
        inCurren=true;
    }
    boolean inLeft=lowestCommonAncestorDFS(root.left,p,q);
    boolean inRight=lowestCommonAncestorDFS(root.right,p,q);
    if(inCurren&&(inLeft||inRight)){
        result=root;
    }
     if(inLeft&&inRight){
        result=root;
    }
    return inLeft||inRight||inCurren;
}

    // public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    //     if(root==null){
    //         return null;
    //     }
    //     TreeNode left=lowestCommonAncestor(root.left,p,q);
    //     TreeNode right=lowestCommonAncestor(root.right,p,q);
    //      if((root.val==p.val||root.val==q.val)&&(left!=null||right!=null)){
    //         return root;
    //     }
    //     if(left!=null&&right!=null){
    //         return root;
    //     }
    //     if(left!=null){
    //         return  left;
    //     }
    //     if(right!=null){
    //         return  right;
    //     }

    //      if(root.val==p.val||root.val==q.val){
    //         return root;
    //     }
    //     return null;
       
        
    // }
}

二叉搜索树中的搜索【二叉树】

 【LeetCode 直通车】:700 二叉搜索树中的搜索(简单)[28]

题解

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
      if(root==null){
          return null;
      }
      if(root.val==val){
          return root;
      }
      if(val>root.val){
          return searchBST(root.right,val);
      }else{
           return searchBST(root.left,val);
      }
        
    }
}

删除二叉搜索树中的节点【二叉树】

 【LeetCode 直通车】:450 删除二叉搜索树中的节点(中等)[29]

题解

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root==null){
            return null;
        }
        if(key>root.val){
            root.right=deleteNode(root.right,key);
        }else if(key

完全二叉树的节点个数【二叉树】

 【LeetCode 直通车】:222 完全二叉树的节点个数(中等)[30]

题解

class Solution {
    public int countNodes(TreeNode root) {
        if(root==null){
            return 0;
        }
        int leftHeight=0;
        TreeNode leftTree=root;
        while(leftTree.left!=null){
            leftTree=leftTree.left;
            leftHeight++;
        }
         int rightHeight=0;
        TreeNode rightTree=root;
        while(rightTree.right!=null){
            rightTree=rightTree.right;
            rightHeight++;
        }
        if(leftHeight==rightHeight){
            return (int)Math.pow(2,leftHeight+1)-1;
        }else{
            return 1+ countNodes(root.left)+countNodes(root.right);
        }
    }
}

二叉树的锯齿形层序遍历【二叉树】

 【LeetCode 直通车】:103 二叉树的锯齿形层序遍历(中等)[31]

题解

class Solution {
    public List> zigzagLevelOrder(TreeNode root) {
        Queue  queue=new LinkedList();
        List> result=new ArrayList>();
        int index=1;
        if(root!=null){
            queue.offer(root);
        }
        while(!queue.isEmpty()){
            int size=queue.size();
            Deque deque=new LinkedList();
            for(int i=0;i

【】高频算法题系列:排序算法

主要有以下几类高频考题:

  • 用最少数量的箭引爆气球【中等】【排序】

  • 合并区间【中等】【排序算法+区间问题】【面试真题】

用最少数量的箭引爆气球【排序算法】

 【LeetCode 直通车】:452 用最少数量的箭引爆气球(中等)[32]

题解

对比435. 无重叠区间

如果按左端升序排序,可能出现这种:[0, 9], [0, 6], [7, 8]

    当前第一个区间和第二个重合,我让当前第一个区间继续寻求重合,它和第三个也重合。
    你想着一箭三雕,但第二个和第三个其实并不重合。
    被「包含」在当前区间的重合区间,不一定和别的重合区间重合
    当前区间可能和很多区间重合,但无法保证这些区间内部都互相重合。

//尾部排序,每个开始和之前的结尾做对比,结尾是有序的,若采用头部排序,后面的头部和结尾比较,结尾无续,可能存在前面的尾部更长,后面两个尾部更短的情况 

class Solution {
    public int findMinArrowShots(int[][] points) {
        if(points==null){
            return 0;
        }
        Arrays.sort(points,new Comparator(){
            public int compare(int []o1,int []o2){
               return  Integer.compare(o1[1], o2[1]);
            }
        });
        int startIndex=points[0][1];
        int result=1;
        for(int i=1;istartIndex){
                result++;
                startIndex=points[i][1];
            }
        }
        return result;
    }
}

合并区间【排序算法+区间问题】

 【LeetCode 直通车】:56 合并区间(中等)[33]

题解

class Solution {
     public int[][] merge(int[][] intervals) {
         if(intervals==null){
             return new int[][]{};
         }
         Arrays.sort(intervals,new Comparator(){
             public int compare(int[]a,int[]b){
                 return Integer.compare(a[0],b[0]);
             }
         });
         List result=new ArrayList();
         result.add(intervals[0]);
         int maxRight=intervals[0][1];
        for(int i=1;i result.get(result.size()-1)[1]){
                 result.add(intervals[i]);
            }else{
                result.get(result.size()-1)[1]=Math.max(intervals[i][1], result.get(result.size()-1)[1]);
            }

        }
        return result.toArray(new int [result.size()][]);

     }
}

高频算法题系列:二分查找

主要有以下几类高频考题:

  • 寻找两个正序数组的中位数【困难】【二分查找】

  • 判断子序列【简单】【二分查找】

  • 在排序数组中查找元素的第一个和最后一个位置【中等】【二分查找】

寻找两个正序数组的中位数【二分查找】

 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难)[34]

题解

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
    let m = nums1.length, n = nums2.length;
    let i = 0, j = 0;
    let newArr = [];
    while (i < m && j < n) {
        if (nums1[i] < nums2[j]) {
            newArr.push(nums1[i++]);
        } else {
            newArr.push(nums2[j++]);
        }
    }
    newArr = newArr.concat(i < m ? nums1.slice(i) : nums2.slice(j));
    const len = newArr.length;
    console.log(newArr)
    if (len % 2 === 0) {
        return (newArr[len / 2] + newArr[len / 2 - 1]) / 2;
    } else {
        return newArr[Math.floor(len / 2)];
    }
};

判断子序列【二分查找】

 【LeetCode 直通车】:392 判断子序列(简单)[35]

题解

class Solution {
    public boolean isSubsequence(String s, String t) {
        if(s==null||t==null){
            return true;
        }
        int m=s.length(),n=t.length(),i=0,j=0;
        if(m>n){
            return false;
        }
        while(i

在排序数组中查找元素的第一个和最后一个位置【二分搜索】

对比二分查找:875. 爱吃香蕉的珂珂

1011. 在 D 天内送达包裹的能力

69. Sqrt(x)

 【LeetCode 直通车】:34 在排序数组中查找元素的第一个和最后一个位置(中等)[36]

题解

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums==null||nums.length==0){
            return new int[]{-1,-1};
        }
        int left=binarySearch(nums,target,true);
         int right=binarySearch(nums,target,false);
         return new int[]{left,right};
        
    }
   public int binarySearch(int []nums,int target,boolean isFirst){
       int left=0,right=nums.length-1;
       while(left<=right){
           int middle=right-(right-left)/2;
           if(isFirst){
               if(target<=nums[middle]){
                   right=middle-1;
               }else{
                   left=middle+1;
               }
           }else{
               if(target>=nums[middle]){
                   left=middle+1;
               }else{
                   right=middle-1;
               }

           }
        
       }
        if(isFirst&&left=0&&nums[right]==target){
            return right;
            
        }
        return -1;
   }
}

【】高频算法题系列:动态规划

主要有以下几类高频考题:

  • 最长递增子序列【中等】【动态规划】

  • 零钱兑换【中等】【动态规划】【面试真题】

  • 最长公共子序列 【中等】【动态规划】【面试真题】

  • 编辑距离 【困难】【动态规划】

  • 最长回文子序列【中等】【动态规划】【面试真题】

  • 最大子序和【简单】【动态规划】【面试真题】

  • 买卖股票的最佳时机系列【系列】【动态规划】【面试真题】

  • 801. 使序列递增的最小交换次数

  • 940. 不同的子序列 II

最长递增子序列【动态规划】

 【LeetCode 直通车】:300 最长递增子序列(中等)[37]

题解

class Solution {
// 考虑往]dp[0…i−1] 中最长的上升子序列后面再加一个 nums[i]。由于dp[j] 代表 nums[0…j] 中以 nums[j] 结尾的最长上升子序列,所以如果
   public int lengthOfLIS(int[] nums) {
		if(nums==null||nums.length==0){
            return 0;
        }
        int []dp=new int [nums.length];
        dp[0]=1;
        int result=0;
        for(int i=0;inums[j]){
                    dp[i]=Math.max(dp[i],dp[j]+1);
                }
            }
            result=Math.max(result,dp[i]);
        }
        return result;

    }
	
}

【面试真题】 零钱兑换【动态规划】

 【LeetCode 直通车】:322 零钱兑换(中等)[38]

题解

class Solution {
    public int coinChange(int[] coins, int amount) {
         int dp[] =new int [amount+1];
         for(int i=1;i<=amount;i++){
             dp[i]=Integer.MAX_VALUE-1;
         }
         dp[0]=0;
        for(int coin:coins){
            for(int j=coin;j<=amount;j++){
                dp[j]=Math.min(dp[j],dp[j-coin]+1);

            }
        }
        return dp[amount]<(Integer.MAX_VALUE-1)?dp[amount]:-1;
    }
}

【面试真题】 最长公共子序列【动态规划】

 【LeetCode 直通车】:1143 最长公共子序列(中等)[39]

题解

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        if(text1==null||text2==null){
            return 0;
        }
        int dp[][]=new int[text1.length()+1][text2.length()+1];
        for(int i=1;i<=text1.length();i++){
            for(int j=1;j<=text2.length();j++){
                if(text1.charAt(i-1)==text2.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
                     dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                }


            }
        }
        return dp[text1.length()][text2.length()];

    }
}

编辑距离【动态规划】

221. 最大正方形

 【LeetCode 直通车】:72 编辑距离(困难)[40]

题解

class Solution {
    public int minDistance(String word1, String word2) {
        int dp[][]=new int[word1.length()+1][word2.length()+1];
        for(int i=0;i<=word1.length();i++){
            dp[i][0]=i;
        }
        for(int i=0;i<=word2.length();i++){
            dp[0][i]=i;
        }
         for(int i=1;i<=word1.length();i++){
            for(int j=1;j<=word2.length();j++){
                if(word1.charAt(i-1)==word2.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1];
                }else{
                    dp[i][j]=Math.min(
                        Math.min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1]
                    )+1;
                }
            }
        }
        return dp[word1.length()][word2.length()];

    }
}

【面试真题】最长回文子序列【动态规划】

 【LeetCode 直通车】:516 最长回文子序列(中等)[41]

题解

class Solution {
    public int longestPalindromeSubseq(String s) {
        if(s==null||s.length()==0){
            return 0;
        }
        int [][]dp=new int[s.length()+1][s.length()+1];
        for(int i=0;i=0;j--){
                if(s.charAt(j)==s.charAt(i)){
                    dp[j][i]=dp[j+1][i-1]+2;
                }else{
                    dp[j][i]=Math.max(dp[j+1][i],dp[j][i-1]);
                }
            }
        }
        return dp[0][s.length()-1];
        
    }
}

【LeetCode 直通车】:5最长回文子串(中等)[41]

题解

class Solution {
   	   
	    public String longestPalindrome(String s) {
            int maxLength=0;
	        String longestPalindromeStr="";
			  if(s==null||s.length()==0){
                  return null;
              }
               if(s.length()==1){
                  return s;
              }
              int dp[][]=new int[s.length()][s.length()];
              for(int i=0;i0&&s.charAt(i)==s.charAt(j)){
                               dp[j][i]=dp[j+1][i-1]+2;
                          }
                      }
                      if(dp[j][i]>maxLength){
                          maxLength=dp[j][i];
                          longestPalindromeStr=s.substring(j,i+1);
                      }
                  }

              }
                if(maxLength==0){
                    return s.substring(0,1);
                }

              return longestPalindromeStr;
	    }
	

    //   public int longestPalindrome=0;
    //   public String longestPalindromeStr;
	//   public String longestPalindrome(String s) {
    //       if(s==null||s.length()==0){
    //           return null;
    //       }
    //       for(int i=0;i=0&&start2longestPalindrome){
    //           longestPalindrome=start2-start1;
    //           longestPalindromeStr=s.substring(start1+1,start2);
    //       }

    //   }
	
}

【面试真题】 最大子序和【动态规划】

对比152. 乘积最大子数组

 【LeetCode 直通车】:53 最大子序和(简单)[42]

题解

class Solution {
     public int maxSubArray(int[] nums) {
         int dp[] =new int[nums.length];  //状态不能定义为前i个连续子数组,状态转移时 i和i-1未必连续,定位为以i为结尾的连续子数组
         if(nums==null||nums.length==0){
             return 0;
         }
         int maxSubArray=nums[0];
         dp[0]=nums[0];
         for(int i=1;i0){  //和大于0,就对后边新的数组有增益,可继续加
    //             result=Math.max(result,tempSum);
    //         }else{
    //             result=Math.max(result,tempSum);
    //             tempSum=0;
    //         }
    //     }
    //     return result;

    // }
}

【面试真题】 买卖股票的最佳时机【动态规划】

  •  【LeetCode 直通车】:121 买卖股票的最佳时机(简单)[43]【面试真题】

  • class Solution {
        public int maxProfit(int[] prices) {
            int minValue=Integer.MAX_VALUE,result=0;
            if(prices==null||prices.length==1){
                return 0;
            }
            for(int price :prices){
                minValue=Math.min(minValue,price);
                result=Math.max(result,price-minValue);
            }
            return result;
    
        }
    }
  •  【LeetCode 直通车】:122 买卖股票的最佳时机 II(简单)[44]

  • class Solution {
    
        // //贪心算法,画个走势上升下降图,每个上升阶段最高点和最低点差值,相当于中间各个点差值相加
        // public int maxProfit(int[] prices) {
        //     if(prices==null||prices.length<2){
        //         return 0;
        //     }
        //     int result=0;
        //     for(int i=1;iprices[i-1]){
        //             result+=(prices[i]-prices[i-1]);
        //         }
        //     }
        //     return result;
    
        // }
    
     public int maxProfit(int[] prices) {
          if(prices==null||prices.length<2){
                return 0;
            }
    		int [][]dp=new int[prices.length][2];  //当前持有股票和未持有股票两种情况
    		dp[0][0]=0;
    		dp[0][1]=-prices[0];
    		for(int i=1;i
  •  【LeetCode 直通车】:123 买卖股票的最佳时机 III(困难)[45]

  •  【LeetCode 直通车】:188 买卖股票的最佳时机IV(困难)[46]

  •  【LeetCode 直通车】:309 买卖股票的最佳时机含冷冻期(中等)[47]

  • class Solution {
        public int maxProfit(int[] prices) {
                    if(prices==null||prices.length<1){
                        return 0;
                    }
    		        int n=prices.length;
    		        int dp [][]=new int [n][3];
    		        //   [i][0]表示今天过后处于冻结未持有,[i][1]表持今天过后持有 ,[i][2] 表示处于非冻结可以买入期
    		        dp [0][1]=-prices[0];
    		      for(int i=1;i
  •  【LeetCode 直通车】:714 买卖股票的最佳时机含手续费(中等)[48]

受限于篇幅,这里只给出第一道题的代码模板,也是一面常考真题,笔者在面试字节跳动时就遇到过。

题解

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
  let dp = [];
  for (let i = -1; i < prices.length; i++) {
    dp[i] = []
    for (let j = 0; j <= 1; j++) {
      dp[i][j] = [];
      dp[i][j][0] = 0;
      dp[i][j][1] = 0;
      if (i === -1) {
        dp[i][j][1] = -Infinity;
      }
      if (j === 0) {
        dp[i][j][1] = -Infinity;
      }
      if (j === -1) {
        dp[i][j][1] = -Infinity;
      }
    }
  }
  for (let i = 0; i < prices.length; i++) {
    for (let j = 1; j <= 1; j++) {
      dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
      dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
    }
  }
  return dp[prices.length - 1][1][0];
};

801. 使序列递增的最小交换次数

class Solution {
    public int minSwap(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int a = 0, b = 1;
        for (int i = 1; i < n; i++) {
            int at = a, bt = b;
            a = b = n;
            if (nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1])  {
                a = Math.min(a, at);
                b = Math.min(b, bt + 1);
            }
            if (nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) {
                a = Math.min(a, bt);
                b = Math.min(b, at + 1);
            }
        }
        return Math.min(a, b);
    }
}

高频算法题系列:BFS

主要有以下几类高频考题:

  • 打开转盘锁【中等】【BFS】

  • 二叉树的最小深度【简单】【BFS】

打开转盘锁【BFS】

 【LeetCode 直通车】:752 打开转盘锁(中等)[49]

题解

class Solution {
   	 public int openLock(String[] deadends, String target) {
		 	Set lockSet=new HashSet();
		 	Set visited=new HashSet();
		 	for(String curLock:deadends){
		 		lockSet.add(curLock);
		 	}
		 	Deque queue=new LinkedList();
		 	queue.offer("0000");
		 	// visited.add("0000");
		 	int minLength=0;
		 	while(!queue.isEmpty()){
		 		int length=queue.size();
		 		for(int j=0;j

二叉树的最小深度【BFS】

 【LeetCode 直通车】:111 二叉树的最小深度(简单)[50]

题解

class Solution {
    public int minDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        Deque queue=new LinkedList();
        queue.offer(root);
        int minDeep=1;
        while(!queue.isEmpty()){
            int length=queue.size();
            for(int i=0;i

【】高频算法题系列:栈

主要有以下几类高频考题:

  • 最小栈【简单】【栈】

  • 有效的括号【中等】【栈】【面试真题】

  • 简化路径【中等】【栈】

  • 下一个更大元素 【系列】【栈】

227. 基本计算器 II(点击看题)

1006. 笨阶乘

769. 最多能完成排序的块

最小栈【栈】

 【LeetCode 直通车】:155 最小栈(简单)[51]

题解

class MinStack {
    Stack  stack;
    Stack  minStack;

    /** initialize your data structure here. */
    public MinStack() {
        stack=new Stack();
        minStack=new Stack();

    }
    
    public void push(int val) {
        stack.push(val);
        minStack.push(minStack.isEmpty()?val:Math.min(minStack.peek(),val));

    }
    
    public void pop() {
        stack.pop();
        minStack.pop();

    }
    
    public int top() {
        return stack.peek();

    }
    
    public int getMin() {
        return minStack.peek();

    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

【系列】下一个更大元素 【栈】

  •  【LeetCode 直通车】:496 下一个更大元素 I(简单)[52]

  •  【LeetCode 直通车】:503 下一个更大元素 II(中等)[53]

受限于篇幅,这里只给出第一道题的代码模板

题解

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
      Map map=new HashMap();
      Stack stack=new Stack();
      int []result=new int[nums1.length];
      for(int i=nums2.length-1;i>=0;i--){
          while(!stack.isEmpty()&&nums2[i]>stack.peek()){
              stack.pop();
          }
          int iResult=stack.isEmpty()?-1:stack.peek();
          stack.push(nums2[i]);
          map.put(nums2[i],iResult);
      }
      for(int i=0;i stack=new Stack();
        int n=nums.length;
        int [] result=new int[n];
        for(int i=2*n-1;i>=0;i--){
            int index=i%n;
            while(!stack.isEmpty()&&stack.peek()<=nums[index]){
                stack.pop();
            }
            int curValue=stack.isEmpty()?-1:stack.peek();
            stack.push(nums[index]);
            result[index]=curValue;
        }
        return result;

    }
}

【面试真题】有效的括号【栈】

 【LeetCode 直通车】:20 有效的括号(中等)[54]

题解

class Solution {
     public static  boolean isValid(String s) {
		 if(s==null||s.length()==0){
			 return true;
		 }
		 while(s.contains("()")||s.contains("{}")||s.contains("[]")){
			s=s.replace("()", "");
			s=s.replace("{}", "");
			s=s.replace("[]", "");
		 }
		 return s.length()>0?false:true;
	    }



    // public static  boolean isValid(String s) {
	// 	 if(s==null||s.length()==0){
	// 		 return true;
	// 	 }
	// 	 Stack stack=new Stack();
	// 	 for(int i=0;i0?false:true;
	// }
}

简化路径【栈】

 【LeetCode 直通车】:71 简化路径(中等)[55]

题解

class Solution {
    public String simplifyPath(String path) {
        if(path==null||"".equals(path)){
            return "/";
        }
        String [] pathArray=path.split("/");
        Stack stack=new Stack();
        for(int i=0;i

【】高频算法题系列:DFS

主要有以下几类高频考题:

  • 岛屿的最大面积【中等】【DFS】

  • 相同的树【简单】【DFS】

岛屿的最大面积【DFS】

 【LeetCode 直通车】:695 岛屿的最大面积(中等)[56]

题解

class Solution {
    public int maxAreaOfIsland=0;
    public int tempMaxAreaOfIsland=0;
    public int maxAreaOfIsland(int[][] grid) {
        int m=grid.length;
        int n=grid[0].length;
        boolean [][]used=new boolean[m][n];
        for(int i=0;igrid.length-1||j<0||j>grid[0].length-1){
            return;
        }
        if(used[i][j]||grid[i][j]==0){
            return;
        }
        tempMaxAreaOfIsland++;
        maxAreaOfIsland=Math.max(maxAreaOfIsland,tempMaxAreaOfIsland);
        used[i][j]=true;

        maxAreaOfIslandDFS(grid,i+1,j,used);
        maxAreaOfIslandDFS(grid,i-1,j,used);
        maxAreaOfIslandDFS(grid,i,j-1,used);
        maxAreaOfIslandDFS(grid,i,j+1,used);

    }
}

相同的树【DFS】

 【LeetCode 直通车】:100 相同的树(简单)[57]

题解

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if((p!=null&&q!=null)&&(p.val==q.val)){
            return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
        }else if(p==null&&q==null){
            return true;
        }else{
            return false;
        }

    }
}

【】高频算法题系列:回溯算法

主要有以下几类高频考题:

  • N皇后【困难】【回溯算法】【面试真题】

  • 全排列【中等】【回溯算法】

  • 括号生成【中等】【回溯算法】

  • 复原 IP 地址【中等】【回溯算法】

  • 子集 【简单】【回溯算法】

【面试真题】N皇后【回溯算法】

 【LeetCode 直通车】:51 N皇后(困难)[58]

题解

class Solution {
    List> result=new ArrayList>();
    public List> solveNQueens(int n) {
        char [][] queenChar=new char[n][n];
        for(int i=0;iqueenChar.length){
            return;  //理论上不可能>n,有所有rowIndex都不满足的,就没有深度遍历了
        }
        if(colIndex==queenChar.length){
            result.add(arrayToList(queenChar));
        }
        //在本行的所有列都暴力遍历一遍
        for(int i=0;i=0;i--){
            if(queenChar[i][rowIndex]=='Q'){
                return false;
            }
        }
         //左上角
        for(int i=colIndex-1,j=rowIndex-1;i>=0&&j>=0;i--,j--){
            if(queenChar[i][j]=='Q'){
                return false;
            }
        }

         //右上角
        for(int i=colIndex-1,j=rowIndex+1;i>=0&&j arrayToList(char [][]queenChar){
        List result=new ArrayList();
        for(char [] tempChar:queenChar){
            String s=new String(tempChar);
            result.add(s);
        }
        return result;
    }
}

全排列【回溯算法】

 【LeetCode 直通车】:46 全排列(中等)[59]

题解

class Solution {
    List> result=new ArrayList>();
    public List> permute(int[] nums) {
        if(nums==null||nums.length==0){
            return new ArrayList();
        }
        permuteDFS(nums,new ArrayList(),new boolean [nums.length]);
        return result;
    }
    public void permuteDFS(int []nums,List tempList,boolean[]used){
        if(tempList.size()==nums.length){
            result.add(new ArrayList(tempList));
            return;
        }
        for(int i=0;i

括号生成【回溯算法】

 【LeetCode 直通车】:22 括号生成(中等)[60]

题解


class Solution {
        List list = new ArrayList<>();
    public List generateParenthesis(int n) {
        if(n==0){
            return new ArrayList();
        }
        generateParenthesisDFS(n,0,0,"");
        return list;
      
    }
   public void generateParenthesisDFS(int n,int l,int right,String tempStr){
        if(l==right&&l==n){
            list.add(tempStr);
        }
        if(l

复原 IP 地址【回溯算法】

 【LeetCode 直通车】:93 复原 IP 地址(中等)[61]

题解

class Solution {
    List result=new ArrayList();
    public List restoreIpAddresses(String s) {
        if(s==null||s.length()==0){
            return result;
        }
        restoreIpAddressesDFS(0,s,4,"");
        return result;
    }
    public void restoreIpAddressesDFS(int startIndex,String s,int n,String tempS){
        if(startIndex==s.length()&&n==0){
            result.add(tempS);
        }
        if(startIndex==s.length()){
            return;
        }
        if(n==0){
            return;
        }
        char curChar=s.charAt(startIndex);
        if(curChar=='0'){
            if(!"".equals(tempS)){
                tempS+=".";
            }
            tempS+=curChar;
            restoreIpAddressesDFS(startIndex+1,s,n-1,tempS);
        }else{
            if(!"".equals(tempS)){
                tempS+=".";
            }
            for(int i=1;i<4;i++){
                if(startIndex+i>s.length()){
                    return;
                }
                String curStr=s.substring(startIndex,startIndex+i);
                if(Integer.valueOf(curStr)>255){
                    return;
                }
                restoreIpAddressesDFS(startIndex+i,s,n-1,tempS+curStr);
            }

        }

    }

}

子集【回溯算法】

 【LeetCode 直通车】:78 子集(中等)[62]

题解

class Solution {
    List> result=new ArrayList>();
    public List> subsets(int[] nums) {
        if(nums==null||nums.length==0){
            return new ArrayList>();
        }
        subsetsDFS(nums,0,new ArrayList());
        return result;
    }
    public void subsetsDFS(int []nums,int start,List tempList){
        result.add(new ArrayList(tempList));
        for(int i=start;i

文末福利

推荐一个非常有帮助的刷算法题的网址,labuladong 的算法小抄[63],通过套路,认准高频题目,直通大厂;这本小炒目前已经出版成书,对应的 Github 仓库[64]也有 86.2K Star,而且作者还在频繁更新,非常值得学习!

❤️谢谢

往期精文

  • 字节跳动最爱考的前端面试题:JavaScript 基础[65]  2696

  • 字节跳动最爱考的前端面试题:CSS 基础[66] 687

  • 字节跳动最爱考的前端面试题:计算机网络基础[67] 761

欢迎关注公众号:图雀社区。 如果你想从零开始以实战的方式学习一门技术,亦或是想动手做一个比较完整的项目以准备面试,相信 「图雀社区」 的内容都能够帮助到你,成为初入前端的你成长路上的指南针。

原创不易

喜欢的话原创不易,给点鼓励吧 ❤️ 别忘了 分享、点赞、在看 三连哦~。

参考资料

[1]

【LeetCode 直通车】:234 回文链表(简单): https://leetcode-cn.com/problems/palindrome-linked-list/

[2]

【LeetCode 直通车】:206 反转链表(简单): https://leetcode-cn.com/problems/reverse-linked-list/

[3]

【LeetCode 直通车】:23 合并K个升序链表(困难): https://leetcode-cn.com/problems/merge-k-sorted-lists/

[4]

【LeetCode 直通车】:25 K 个一组翻转链表(困难): https://leetcode-cn.com/problems/reverse-nodes-in-k-group/

[5]

【LeetCode 直通车】:141 环形链表(简单): https://leetcode-cn.com/problems/linked-list-cycle/

[6]

【LeetCode 直通车】:148 排序链表(中等): https://leetcode-cn.com/problems/sort-list/

[7]

【LeetCode 直通车】:160 相交链表(简单): https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

[8]

【LeetCode 直通车】:5 最长回文子串(中等): https://leetcode-cn.com/problems/longest-palindromic-substring/

[9]

【LeetCode 直通车】:14 最长公共前缀(简单): https://leetcode-cn.com/problems/longest-common-prefix/

[10]

【LeetCode 直通车】:3 无重复字符的最长子串(中等): https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

[11]

【LeetCode 直通车】:76 最小覆盖子串(困难): https://leetcode-cn.com/problems/minimum-window-substring/

[12]

【LeetCode 直通车】:354 俄罗斯套娃信封问题(困难): https://leetcode-cn.com/problems/russian-doll-envelopes/

[13]

【LeetCode 直通车】:674 最长连续递增序列(简单): https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/

[14]

【LeetCode 直通车】:128 最长连续序列(困难): https://leetcode-cn.com/problems/longest-consecutive-sequence/

[15]

【LeetCode 直通车】:11 盛最多水的容器(中等): https://leetcode-cn.com/problems/container-with-most-water/

[16]

【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难): https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

[17]

【LeetCode 直通车】:26 删除有序数组中的重复项(简单): https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

[18]

【LeetCode 直通车】:695 岛屿的最大面积(中等): https://leetcode-cn.com/problems/max-area-of-island/

[19]

【LeetCode 直通车】:560 和为K的子数组(中等): https://leetcode-cn.com/problems/subarray-sum-equals-k/

[20]

【LeetCode 直通车】:1 两数之和(简单): https://leetcode-cn.com/problems/two-sum/

[21]

【LeetCode 直通车】:167 两数之和 II - 输入有序数组(简单): https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/

[22]

【LeetCode 直通车】:15 三数之和(中等): https://leetcode-cn.com/problems/3sum/

[23]

【LeetCode 直通车】:18 四数之和(中等): https://leetcode-cn.com/problems/4sum/

[24]

【LeetCode 直通车】:42 接雨水(困难): https://leetcode-cn.com/problems/trapping-rain-water/

[25]

【LeetCode 直通车】:55 跳跃游戏(中等): https://leetcode-cn.com/problems/jump-game/

[26]

【LeetCode 直通车】:45 跳跃游戏 II(中等): https://leetcode-cn.com/problems/jump-game-ii/

[27]

【LeetCode 直通车】:236 二叉树的最近公共祖先(简单): https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

[28]

【LeetCode 直通车】:700 二叉搜索树中的搜索(简单): https://leetcode-cn.com/problems/search-in-a-binary-search-tree/

[29]

【LeetCode 直通车】:450 删除二叉搜索树中的节点(中等): https://leetcode-cn.com/problems/delete-node-in-a-bst/

[30]

【LeetCode 直通车】:222 完全二叉树的节点个数(中等): https://leetcode-cn.com/problems/count-complete-tree-nodes/

[31]

【LeetCode 直通车】:103 二叉树的锯齿形层序遍历(中等): https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/

[32]

【LeetCode 直通车】:452 用最少数量的箭引爆气球(中等): https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/

[33]

【LeetCode 直通车】:56 合并区间(中等): https://leetcode-cn.com/problems/merge-intervals/

[34]

【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难): https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

[35]

【LeetCode 直通车】:392 判断子序列(简单): https://leetcode-cn.com/problems/is-subsequence/

[36]

【LeetCode 直通车】:34 在排序数组中查找元素的第一个和最后一个位置(中等): https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

[37]

【LeetCode 直通车】:300 最长递增子序列(中等): https://leetcode-cn.com/problems/longest-increasing-subsequence/

[38]

【LeetCode 直通车】:322 零钱兑换(中等): https://leetcode-cn.com/problems/coin-change/

[39]

【LeetCode 直通车】:1143 最长公共子序列(中等): https://leetcode-cn.com/problems/longest-common-subsequence/

[40]

【LeetCode 直通车】:72 编辑距离(困难): https://leetcode-cn.com/problems/edit-distance/

[41]

【LeetCode 直通车】:516 最长回文子序列(中等): https://leetcode-cn.com/problems/longest-palindromic-subsequence/

[42]

【LeetCode 直通车】:53 最大子序和(简单): https://leetcode-cn.com/problems/maximum-subarray/

[43]

【LeetCode 直通车】:121 买卖股票的最佳时机(简单): https://leetcode-cn.com/problems/container-with-most-water/

[44]

【LeetCode 直通车】:122 买卖股票的最佳时机 II(简单): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

[45]

【LeetCode 直通车】:123 买卖股票的最佳时机 III(困难): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/

[46]

【LeetCode 直通车】:188 买卖股票的最佳时机IV(困难): https://leetcode-cn.com/problems/container-with-most-water/

[47]

【LeetCode 直通车】:309 买卖股票的最佳时机含冷冻期(中等): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

[48]

【LeetCode 直通车】:714 买卖股票的最佳时机含手续费(中等): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/

[49]

【LeetCode 直通车】:752 打开转盘锁(中等): https://leetcode-cn.com/problems/open-the-lock/

[50]

【LeetCode 直通车】:111 二叉树的最小深度(简单): https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/

[51]

【LeetCode 直通车】:155 最小栈(简单): https://leetcode-cn.com/problems/min-stack/submissions/

[52]

【LeetCode 直通车】:496 下一个更大元素 I(简单): https://leetcode-cn.com/problems/next-greater-element-i/

[53]

【LeetCode 直通车】:503 下一个更大元素 II(中等): https://leetcode-cn.com/problems/next-greater-element-ii/

[54]

【LeetCode 直通车】:20 有效的括号(中等): https://leetcode-cn.com/problems/valid-parentheses/

[55]

【LeetCode 直通车】:71 简化路径(中等): https://leetcode-cn.com/problems/simplify-path/

[56]

【LeetCode 直通车】:695 岛屿的最大面积(中等): https://leetcode-cn.com/problems/max-area-of-island/

[57]

【LeetCode 直通车】:100 相同的树(简单): https://leetcode-cn.com/problems/same-tree/

[58]

【LeetCode 直通车】:51 N皇后(困难): https://leetcode-cn.com/problems/n-queens/

[59]

【LeetCode 直通车】:46 全排列(中等): https://leetcode-cn.com/problems/permutations/

[60]

【LeetCode 直通车】:22 括号生成(中等): https://leetcode-cn.com/problems/generate-parentheses/

[61]

【LeetCode 直通车】:93 复原 IP 地址(中等): https://leetcode-cn.com/problems/restore-ip-addresses/

[62]

【LeetCode 直通车】:78 子集(中等): https://leetcode-cn.com/problems/subsets/

[63]

labuladong 的算法小抄: https://www.yuque.com/tuture/interview/labuladong:https

[64]

Github 仓库: https://github.com/labuladong/fucking-algorithm

[65]

字节跳动最爱考的前端面试题:JavaScript 基础: https://juejin.cn/post/6934500357091360781

[66]

字节跳动最爱考的前端面试题:CSS 基础: https://juejin.cn/post/6936913689115099143

[67]

字节跳动最爱考的前端面试题:计算机网络基础: https://juejin.cn/post/6939691851746279437

 

算法分类汇总_第1张图片

前端技术优选

为你精选前端领域优质技术博文,欢迎关注。

61篇原创内容

公众号

 

你可能感兴趣的:(算法,算法,面试,链表,1024程序员节)