代码随想录打卡

代码随想录

1.数组部分

1.1二分查找

在这里插入图片描述

class Solution {
    public int search(int[] nums, int target) {
        if(nums.length==0)return -1;
        int l=0,r=nums.length-1;
        while(l<=r){
            int mid=l+r>>1;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]<target){
                l=mid+1;
            }else{
                r=mid-1;
            }
        }
        return -1;

    }
}

1.2移除元素

在这里插入图片描述
在这里插入图片描述

class Solution {
    //双指针算法
    public int removeElement(int[] nums, int val) {
        int i=0;//标记目前位置 
        for(int j=0;j<nums.length;j++){
            if(nums[j]!=val){
                nums[i]=nums[j];
                i++;
            }
        }
        return i;
    }
}

1.3 有序数组的平方

在这里插入图片描述

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n=nums.length;
        int[] ans=new int[n];
        int k=n-1;
        int i=0,j=nums.length-1;
        //类似于归并排序
        while(i<=j){
            if(nums[i]*nums[i]<nums[j]*nums[j]){
                ans[k--]=nums[j]*nums[j];
                j--;
            }else{
                ans[k--]=nums[i]*nums[i];
                i++;
            }
            
        }
        return ans;

    }
}

1.4长度最小的子数组

在这里插入图片描述

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int minlen=0x3f3f3f3f;
        int sum=0;
        int j=0;
        for(int i=0;i<nums.length;i++){
            sum+=nums[i];
            while(sum>=target){//缩小区间
                minlen=Math.min(minlen,i-j+1);
                sum-=nums[j];
                j++;//   
            }
           
        }
        if(minlen==0x3f3f3f3f)return 0;
        return minlen;
    }
}

1.5螺旋矩阵II

在这里插入图片描述

class Solution {
    static boolean[][] st;
    public int[][] generateMatrix(int n) {
        st=new boolean[n][n];
        int[] dx={0,1,0,-1},dy={1,0,-1,0};
        int[][] ans=new int[n][n];
        int x=0,y=0,d=0;//横,纵坐标,转向指针
        for(int i=1;i<=n*n;i++){
            ans[x][y]=i;
            st[x][y]=true;
            int a=x+dx[d],b=y+dy[d];
            if(a<0 || a>=n || b<0 || b>=n || st[a][b]){
                d=(d+1)%4;
                a=x+dx[d];
                b=y+dy[d];
            }
            x=a;
            y=b;
            
        }
        return ans;
    }
}

2. 链表部分

2.1移除链表元素

在这里插入图片描述

/**
 * 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 removeElements(ListNode head, int val) {
        if(head==null)return null;
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode cur=dummy;
        while(cur.next!=null){
            if(cur.next.val==val){
                cur.next=cur.next.next;
            }else cur=cur.next;
        }
        return dummy.next;

    }
}

2.2设计链表

2.3反转链表

在这里插入图片描述

/**
 * 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 reverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;

    }
}

2.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 swapPairs(ListNode head) {
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode cur=dummy;
        while(cur.next!=null && cur.next.next!=null){
            ListNode a=cur.next;
            ListNode b=cur.next.next;
            cur.next=b;
            a.next=b.next;
            b.next=a;
            cur=a;
        }
        return dummy.next;
    }
}

2.5删除链表的倒数第n个节点

在这里插入图片描述

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode cur=head;
        int cnt=0;
        while(cur!=null){
            cnt++;
            cur=cur.next;
        }
        cur=dummy;
        cnt=cnt-n;
        while(cnt-->0)cur=cur.next;
        cur.next=cur.next.next;
        return dummy.next;
    }
}

2.6环形链表II

‘

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow=hasCycle(head);
        if(slow==null)return null;
        else{
            ListNode fast=head;
            while(fast!=slow){
                fast=fast.next;
                slow=slow.next;
            }
        }
        return slow;
        
        
        
    }
    public static ListNode hasCycle(ListNode head){
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow)return slow;
        }
        return null;
    
    }
}

2.7链表相交

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null || headB==null)return null;
        int lenA=len(headA);
        int lenB=len(headB);
        ListNode curA=headA;
        ListNode curB=headB;
        if(lenA>lenB){
            int t=lenA-lenB;
            for(int i=0;i<t;i++){
                curA=curA.next;
            }
            while(curA!=null && curA!=curB){
                curA=curA.next;
                curB=curB.next;
            }
            return curA;
        }else{
            int t=lenB-lenA;
            for(int i=0;i<t;i++){
                curB=curB.next;
            }
            while(curA!=null && curA!=curB){
                curA=curA.next;
                curB=curB.next;
            }
            return curA;
        } 
    }
    public static int len(ListNode head){
        int cnt=0;
        ListNode cur=head;
        while(cur!=null){
            cnt++;
            cur=cur.next;
            
        }
        return cnt;
    }

}

3.哈希表

3.1有效的字母异位词

在这里插入图片描述

class Solution {
//可以进一步优化,一个+一个- 判断是否为0
    public boolean isAnagram(String s, String t) {
        int[] cnts=help(s);
        int[] cntt=help(t);
        for(int i=0;i<26;i++){
            if(cnts[i]!=cntt[i])return false;
        }
        return true;
    }
    //字符统计
    public static int[] help(String str){
        char[] ch=str.toCharArray();
        int[] cnt=new int[26];
        for(int i=0;i<ch.length;i++){
            cnt[ch[i]-'a']++;
        }
        return cnt;
    }
}

3.2两个数组的交集

在这里插入图片描述

class Solution {
 
    public int[] intersection(int[] nums1, int[] nums2) {
        ArrayList<Integer> ans=new ArrayList<>();
        boolean[] st=new boolean[1010];
        for(int num:nums1){
            st[num]=true;
        }
        for(int num:nums2){
            if(st[num]){
                ans.add(num);
                st[num]=false;
            }
        }
        int[] res=new int[ans.size()];
        for(int i=0;i<ans.size();i++){
            res[i]=ans.get(i);
        }
        return res;
       

    }
}

3.3欢乐数

在这里插入图片描述

class Solution {
    //双指针或者统计出现过的数
    public boolean isHappy(int n) {
        Set<Integer> set=new HashSet<>();
        while(n!=1 && !set.contains(n)){
            set.add(n);
            // System.out.println(n);
            n=get(n);

        }
        return n==1;

    }
    public static int get(int x){
        int res=0;
        while(x!=0){
            int t=x%10;
            res+=t*t;
            x/=10;
        }
        return res;
    }
}

3.4快乐数

在这里插入图片描述

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i]) )return new int[]{map.get(target-nums[i]),i};
            map.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}

3.5两数之和

在这里插入图片描述

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i]) )return new int[]{map.get(target-nums[i]),i};
            map.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}

3.6四数相加

在这里插入图片描述

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        HashMap<Integer,Integer> map=new HashMap<>();
        int res=0;
        int n=nums1.length;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int t=nums1[i]+nums2[j];
                map.put(-t,map.getOrDefault(-t,0)+1);       
            }
        }
        //优化得到On^2
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int num=nums3[i]+nums4[j];
                if(map.containsKey(num))res+=map.get(num);
            }
        }
        return res;
    }
}

3.7赎金信

*加粗样式

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] cnt=new int[26];
        char[] chm=magazine.toCharArray();
        for(char c:chm){
            cnt[c-'a']++;
        }
        char[] chr=ransomNote.toCharArray();
        for(char c:chr){
            cnt[c-'a']--;
        }
        for(int i=0;i<26;i++){
            if(cnt[i]<0)return false;
        }
        return true;
    }
}

3.8三数之和

在这里插入图片描述

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans=new ArrayList<>();
        for(int i=0;i<nums.length-1;i++){
            //排序之后如果第一个元素大于0,则无论任何组合都不能符合要求
            if(nums[i]>0)return ans;
            if( i>0 && nums[i]==nums[i-1])continue;//对第一个数进行去重
        //针对[i+1,n-1]我们可以使用双指针算法
        int j=i+1,k=nums.length-1;
        while(j<k){
            int sum=nums[i]+nums[j]+nums[k];
            if(sum>0){
                k--;
            }else if(sum<0){
                j++;
            }else{
                //符合要求后我们将加入答案
                ans.add(Arrays.asList(nums[i],nums[j],nums[k]));
                while(j<k && nums[j]==nums[j+1])j++;
                while(j<k && nums[k]==nums[k-1])k--;
                k--;
                j++;
            }
        }
        }
        //对i的去重
        return ans;

    }
}

3.9四数之和

在这里插入图片描述

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        // target=(long)target;
        List<List<Integer>> ans=new ArrayList<>();
        Arrays.sort(nums);
        int n=nums.length;
        
        for(int i=0;i<n-3;i++){
            if(i>0 && nums[i]==nums[i-1])continue;
            if(nums[i]>0 && nums[i]>target)return ans;
            for(int j=i+1;j<n-2;j++){
                if(j>i+1&& nums[j]==nums[j-1])continue;
       
                int l=j+1,r=n-1;
                while(l<r){
                    long sum=(long)(nums[i]+nums[j]+nums[l]+nums[r]);
                    if(sum>Integer.MAX_VALUE)continue;
                    if(sum>target){
                        r--;
                    }else if(sum<target){
                        l++;
                    }else if(sum==target){
                        ans.add(Arrays.asList(nums[i],nums[j],nums[l],nums[r]));
                        while(l<r && nums[r]==nums[r-1]){
                            r--;
                        }
                        while(l<r && nums[l]==nums[l+1]){
                            l++;
                        }
                        l++;
                        r--;
                    }
                }
            }
        }
        return ans;
    }
}

4.字符串

4.1反转字符串

在这里插入图片描述

class Solution {
    public void reverseString(char[] s) {
        int i=0,j=s.length-1;
        char tmp='a';
        while(i<j){
            tmp=s[i];
            s[i]=s[j];
            s[j]=tmp;
            i++;
            j--;
        }
    }
}

4.2反转字符串II

在这里插入图片描述

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch=s.toCharArray();
        int n=ch.length;
        int tmp=n/(2*k);
        for(int i=0;i<tmp;i++){
            int l=0+i*2*k;
            int r=l+k-1;
            while(l<r){
                char t=ch[l];
                ch[l]=ch[r];
                ch[r]=t;
                l++;
                r--;
            }
        }
        // System.out.println(n%(2*k));
        int l=tmp*2*k;
        int r=n-1;
        if(n%(2*k)>=k){
           l=0+tmp*2*k;
           r=l+k-1;
        }
         while(l<r){
                char t=ch[l];
                ch[l]=ch[r];
                ch[r]=t;
                l++;
                r--;
            }
        return new String(ch);
    }
}

4.3替换空格

在这里插入图片描述

class Solution {
    public String replaceSpace(String s) {
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)==' '){
                sb.append("%20");
            }else{
                sb.append(s.charAt(i));
            }
        }
        return new String(sb);

    }
}

4.4反转字符串里的单词

在这里插入图片描述

class Solution {
    public String reverseWords(String s) {
        if(s.length()==0)return "";
        int i=0,j=s.length()-1;
        while(i<s.length() && s.charAt(i)==' ')i++;
        while(j>=0 && s.charAt(j)==' ')j--;
        if(i>j)return "";
        StringBuilder sb=new StringBuilder();
        
        //直接使用StringBuilder进行遍历,去除空格
        while(i<=j){
            char c=s.charAt(i);
            //这里第二个条件十分巧妙,当有连续两个空格是,只会加第一个
            if(c!=' ' || sb.charAt(sb.length()-1)!=' ')sb.append(c);
            i++;
        }
        //反转整个字符串
        reverse(sb,0,sb.length()-1);
        //反转单个单词
        i=0;
        while(i<sb.length()){
            j=i;
            while(j<sb.length() && sb.charAt(j)!=' ')j++;
            reverse(sb,i,j-1);
            i=j+1;
        }
        return sb.toString();


        
    }
    //反转指定区间的字符串[]
    public StringBuilder reverse(StringBuilder sb,int l,int r){
        while(l<r){
            char t=sb.charAt(l);
            sb.setCharAt(l,sb.charAt(r));
            sb.setCharAt(r,t);
            l++;
            r--;
        }
        return sb;
    }
}

思路解析

if(c!=' ' || sb.charAt(sb.length()-1)!=' ')sb.append(c);:第二个条件确保我们可以单词间只加一个空格,值得注意
整体思路在于:去空,先将整个单词反转,而后逐个反转每个单词

  • 该方法尽管只是O(n)级别的复杂度,但是需要扫描两边,我们接下来看一中只需要扫描一遍的做法
class Solution {
//代码整体更加简洁
    public String reverseWords(String s) {
        char[] sc=s.toCharArray();
        StringBuilder sb=new StringBuilder();
        //去除首尾空格
        int left=0,right=sc.length-1;
        while(sc[left]==' ')left++;
        while(sc[right]==' ')right--;

//right永远指向当前单词的最后一个位置,
//index+1:用来搜寻,当前单词的第一个位置(index定位到空格)
        while(left<=right){
            //倒着扫描
            int index=right;
            //确定最后一个单词的起始位置
            while(index>=left && sc[index]!=' ')index--;
            for(int i=index+1;i<=right;i++){
                sb.append(sc[i]);
            }
            //如果不是第一个单词,后面加一个空格
            if(index>left)sb.append(' ');
            //指针移动至下一个单词的末尾
            while(index>=left && sc[index]==' ')index--;
            right=index;
        }
        return sb.toString();
    }
}

4.5左旋字符串

在这里插入图片描述

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] ch=s.toCharArray();
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<ch.length;i++){
            sb.append(ch[(n)%ch.length]);
            n=n+1;
        
        }
        return sb.toString();

    }
}

4.6找出字符串中第一个匹配项的下标

在这里插入图片描述

思路分析

  • 经典的KMP算法,直接使用即可
class Solution {
    //KMP算法
    static int[] next;
    public int strStr(String haystack, String needle) {
        int n=haystack.length();
        int m=needle.length();
        char[] ch=(" "+haystack).toCharArray();
        char[] cn=(" "+needle).toCharArray();
        next=new int[cn.length];
        next(cn);
        for(int i=1,j=0;i<=n;i++){
            
       
            while(j!=0 && ch[i]!=cn[j+1])j=next[j];
            if(ch[i]==cn[j+1])j++;

            if(j==m)return (i-m);
        }
        return -1;


    }
    public static void next(char[] ch){
        int n=ch.length;
        //next[1]指定为0
        for(int i=2,j=0;i<n;i++){
            while(j!=0 && ch[i]!=ch[j+1])j=next[j];
            if(ch[i]==ch[j+1])j++;
            next[i]=j;
        }
    }
}

4.7重复的子字符串

在这里插入图片描述

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int n=s.length();


        char[] ch=(" "+s).toCharArray();
        int[] ne=new int[n+1];
        for(int i=2,j=0;i<=n;i++){
            while(j!=0 && ch[i]!=ch[j+1])j=ne[j];
            if(ch[i]==ch[j+1])j++;
            ne[i]=j;
        }
        int t=n-ne[n];
        return (t<n && n%t==0);
    }
}

5双指针

5.1移除元素

在这里插入图片描述
在这里插入图片描述

  • 快慢指针
class Solution {
    public int removeElement(int[] nums, int val) {
        //一个指针指向当前位置,一个指向需要更换的位置
        int n=nums.length;
        int i=0,j=0;
        while(j<n){
            while(j<n && nums[j]==val)j++;
            // System.out.println(i+" "+j);
            if(j>=n)break;
            int t=nums[i];
            nums[i]=nums[j];
            nums[j]=t;
            j++;
            i++;
        }
        return i;
    }
}

5.2反转字符串

在这里插入图片描述

class Solution {
    public void reverseString(char[] s) {
        int i=0,j=s.length-1;
        while(i<j){
            char t=s[i];
            s[i]=s[j];
            s[j]=t;
            i++;
            j--;
        }
        // return s;

    }
}

5.3反转字符串中的单词

在这里插入图片描述

class Solution {
    public String reverseWords(String s) {
        char[] ch=s.toCharArray();
        int l=0,r=s.length()-1;
        //去除首尾空格
        while(ch[l]==' ')l++;
        while(ch[r]==' ')r--;
        //倒着扫描
        StringBuilder sb=new StringBuilder();
        while(l<=r){
            int i=r;
            while(i>=l && ch[i]!=' ')i--;
            for(int j=i+1;j<=r;j++)sb.append(ch[j]);
            if(i>l)sb.append(" ");
            //指针移动
            r=i; 
            //移到下一个单词末尾
            while(r>=l && ch[r]==' ')r--;
        }
        return new String(sb);

    }
}

5.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 reverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }
}

5.5删除链表的倒数第n个节点

在这里插入图片描述

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode dummy=new ListNode(-1);
        dummy.next=head;
        ListNode fast=dummy;
        ListNode slow=dummy;
        for(int i=0;i<=n;i++)fast=fast.next;
        while(fast!=null){
            slow=slow.next;
            fast=fast.next;

        }
        slow.next=slow.next.next;
        return dummy.next;
    }
}

6.栈与队列

6.1用栈实现队列

在这里插入图片描述

class MyQueue {
    static ArrayDeque<Integer> sta;
    static ArrayDeque<Integer> h;
    public MyQueue() {
        sta=new ArrayDeque<>();
        h=new ArrayDeque<>();
    }
    
    public void push(int x) {
        sta.push(x);

    }
    
    public int pop() {
        if(!h.isEmpty()){
            return h.pop();
        }else{
            while(!sta.isEmpty()){
                h.push(sta.pop());
            }
        }
        return h.pop();
    }
    
    public int peek() {
        if(!h.isEmpty()){
            return h.peek();
        }else{
            while(!sta.isEmpty()){
                h.push(sta.pop());
            }
        }
        return h.peek();
        

    }
    
    public boolean empty() {
        return sta.isEmpty()&&h.isEmpty();

    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

6.2用队列模拟栈

在这里插入图片描述

class MyStack {
    ArrayDeque<Integer> q;
    public MyStack() {
        q=new ArrayDeque<>();
    }
    
    public void push(int x) {
        q.offer(x);
        int size=q.size();
        size--;
        while(size-->0){
            q.offer(q.poll());
        }
    }
    
    public int pop() {
        return q.poll();
    }
    
    public int top() {
        return q.peek();
    }
    
    public boolean empty() {
        return q.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

6.3有效得括号

6.4 删除字符串中所有相邻得重复项

6.5逆波兰表达式求值

在这里插入图片描述

class Solution {
    public int evalRPN(String[] tokens) {
        ArrayDeque<Integer> sta=new ArrayDeque<>();
        for(int i=0;i<tokens.length;i++){
            if(isNumeric(tokens[i]))sta.push(Integer.parseInt(tokens[i]));
            else{
                int b=sta.pop();
                int a=sta.pop();
                sta.push(cal(a,b,tokens[i]));
            }
        }
        return sta.pop();

    }
    public int cal(int a,int b,String m){
        if(m.equals("+"))return a+b;
        if(m.equals("-"))return a-b;
        if(m.equals("*"))return a*b;
        if(m.equals("/"))return a/b;
        return 0;
    }
     public static boolean isNumeric(String str) {
        return str.matches("-?\\d+(\\.\\d+)?"); // 使用正则表达式判断是否为数字
    }
}

6.6滑动窗口最大值

在这里插入图片描述

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n=nums.length;
        int m=0;
        int[] ans=new int[n-k+1];
        ArrayDeque<Integer> q=new ArrayDeque<>();
        for(int i=0;i<nums.length;i++){
            if(!q.isEmpty() && i-q.peek()>=k)q.poll();
            
            while(!q.isEmpty()&& nums[i]>=nums[q.peekLast()]){
                // if(i==3)System.out.println(nums[q.peek()]);
                q.pollLast();
            }  
            q.offer(i);        
             if(i>=k-1){
            
                ans[m++]=nums[q.peek()];

            }
        }
        return ans;

    }
}

6.7前k个高频元素

在这里插入图片描述

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
         PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
         Map<Integer,Integer> map=new HashMap<>();
         for(int num:nums)map.put(num,map.getOrDefault(num,0)+1);
         for(var x:map.entrySet()){
             int[] tmp=new int[2];
             tmp[0]=x.getKey();
             tmp[1]=x.getValue();
             pq.add(tmp);
         }
         while(pq.size()>k)pq.poll();
         int[] ans=new int[k];
         for(int i=0;i<k;i++){
             ans[i]=pq.poll()[0];
         }
         return ans;

    }
}

7.二叉树

7.1 二叉树的递归遍历

前序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        pre(res,root);
        return res;
        
    }
    static void pre(List<Integer> res,TreeNode root){
        if(root==null)return;
        res.add(root.val);
        pre(res,root.left);
        pre(res,root.right);
    }
}

后序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //迭代解决
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        posOrder(root,ans);
        return ans;


    }
    private void posOrder(TreeNode root,List<Integer> ans){
        if(root==null){
            return;
            
        }
        posOrder(root.left,ans);
            posOrder(root.right,ans);
            ans.add(root.val);
    }
}

中序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        in(root,res);
        return res;

    }
    static void in(TreeNode root,List<Integer> res){
        if(root==null)return;
        in(root.left,res);
        res.add(root.val);
        in(root.right,res);
      
    }
}

7.2 二叉树的迭代遍历

前序遍历

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)return res;
        ArrayDeque<TreeNode> sta=new ArrayDeque<>();
        sta.push(root);
        while(!sta.isEmpty()){
	        TreeNode t=sta.pop();
	        res.add(t.val);
	        if(t.right!=null)sta.push(t.right);
	        if(t.left!=null)sta.push(t.left);
        }
          return res;
    }  
}

后序遍历

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)return res;
        ArrayDeque<TreeNode> sta=new ArrayDeque<>();
        sta.push(root);
        while(!sta.isEmpty()){
            TreeNode t=sta.pop();
            res.add(0,t.val);
            //因为我们要进行反转,所以先入左节点,后右节点,弹出(右左),反转(左右)
            if(t.left!=null)sta.push(t.left);
            if(t.right!=null)sta.push(t.right);

        }
       
        return res;

    }
}

中序遍历

 Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        ArrayDeque<TreeNode> sta=new ArrayDeque<>();
        while(root!=null || !sta.isEmpty()){
            while(root!=null){//只要结点的左子树不空,就向左遍历
                sta.push(root);
                root=root.left;               
            }
            if(!sta.isEmpty()){//将所有的左子树节点加入之后我们进行遍历
                root=sta.pop();//将当前栈顶元素弹出
                res.add(root.val);//遍历该元素
                root=root.right;//遍历该元素的右子树
            }
        }
        return res;

    }
}

7.3二叉树的层序遍历

在这里插入图片描述

/**
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans=new ArrayList<>();
        if(root==null)return ans;
        ArrayDeque<TreeNode> q=new ArrayDeque<>();
        q.offer(root);
        
        while(!q.isEmpty()){
            int size=q.size();
            List<Integer> level=new ArrayList<>();
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                level.add(t.val);
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
            }
            ans.add(level);
        }
        return ans;
        

    }
}

7.4二叉树的层序遍历II

在这里插入图片描述

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> ans=new ArrayList<>();
        if(root==null)return ans;
        ArrayDeque<TreeNode> q=new ArrayDeque<>();
        q.offer(root);
        
        while(!q.isEmpty()){
            int size=q.size();
            List<Integer> level=new ArrayList<>();
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                level.add(t.val);
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
            }
            ans.add(0,level);
        }
        return ans;

    }
}

7.5二叉树的右视图

在这里插入图片描述

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        ArrayDeque<TreeNode> q=new ArrayDeque<>();
        if(root==null)return ans;
        q.offer(root);
        while(!q.isEmpty()){
            int size=q.size();
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                if(i==size-1)ans.add(t.val);
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
                
            }
        }
        return ans;


    }
}

7.6二叉树的层平均值

在这里插入图片描述


class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> ans=new ArrayList<>();
        ArrayDeque<TreeNode> q=new ArrayDeque<>();
        if(root==null)return ans;
        q.offer(root);
        while(!q.isEmpty()){
            int size=q.size();
            double sum=0;
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                sum+=(double)t.val;
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
                if(i==size-1)ans.add(sum/(double)size);
            }
        }
        return ans;


    }
}

7.7N叉树的层序遍历

在这里插入图片描述

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/
class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> ans=new ArrayList<>();
        ArrayDeque<Node> q=new ArrayDeque<>();
        if(root==null)return ans;
        q.offer(root);
        while(!q.isEmpty()){
            int size=q.size();
            List<Integer> level=new ArrayList<>();
            for(int i=0;i<size;i++){
                Node t=q.poll();
             
                level.add(t.val);
                for(Node node:t.children){
                    if(node!=null)q.offer(node);
                }
            }
            ans.add(level);
        }
        return ans;
        
    }
}

7.8树中每行得最大值

在这里插入图片描述

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        ArrayList<Integer> ans=new ArrayList<>();
        ArrayDeque<TreeNode> q=new ArrayDeque<TreeNode>();
        if(root==null)return ans;
        q.offer(root);
        while(!q.isEmpty()){
            int size=q.size();
            int max=q.peek().val;
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                max=Math.max(max,t.val);
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
            }
            ans.add(max);
        }
        return ans;
    }
}

7.9返回二叉树的最大深度

在这里插入图片描述

class Solution {
    public int maxDepth(TreeNode root) {
        return dfs(root);
    }
    public static int dfs(TreeNode root){
        if(root==null)return 0;
        return Math.max(dfs(root.left),dfs(root.right))+1;
    }
}

7.10二叉树得最小深度

在这里插入图片描述

class Solution {
    //注意最小深度得定义:最近得叶子节点到根节点得节点数量
    public int minDepth(TreeNode root) {
        if(root==null)return 0;
        //左右全为空
        if(root.left==null && root.right==null)return 1;
        //左右一个为空
        if(root.left==null || root.right==null)return minDepth(root.left)+minDepth(root.right)+1;
        if(root.left!=null && root.right!=null)return Math.min(minDepth(root.left),minDepth(root.right))+1;
        return 0;
    }
}

7.11反转二叉树

在这里插入图片描述

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null)return root;
        TreeNode t=root.left;
        root.left=root.right;
        root.right=t;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

7.12对称二叉树

在这里插入图片描述

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null)return true;
        return compare(root.left,root.right);

    }
    static boolean compare(TreeNode left,TreeNode right){
        if(right==null && left==null)return true;
        else if(right==null || left==null)return false;
        else if(right!=null && left!=null && left.val!=right.val)return false;
        return compare(left.left,right.right)&&compare(left.right,right.left);
    }
}

7.13完全二叉树节点的个数

在这里插入图片描述

class Solution {
    public int countNodes(TreeNode root) {
        //根据完全二叉树进行改进
        if(root==null)return 0;
        TreeNode left=root;
        TreeNode right=root;
        int lc=0,rc=0;
        while(left!=null){
            left=left.left;
            lc++;
        }
        while(right!=null){
            right=right.right;
            rc++;
        }
        if(lc==rc)return (int)Math.pow(2,lc)-1;
        return countNodes(root.left)+countNodes(root.right)+1;

    }
}

7.14平衡二叉树

在这里插入图片描述

class Solution {
    static boolean ans;
    public boolean isBalanced(TreeNode root) {
        ans=true;
        dfs(root);
        return ans;
    }
    static int dfs(TreeNode root){
        if(root==null)return 0;
        int l=dfs(root.left);
        int r=dfs(root.right);
        if(Math.abs(l-r)>1)ans=false;
        return Math.max(l,r)+1;
    }
}

7.15二叉树的所有路径

在这里插入图片描述

class Solution {
    List<String> path=new ArrayList<>();
    static List<String> ans=new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        ans.clear();
        if(root==null)return ans;
        dfs(root,""+root.val);
        return ans;
    }
    public static void dfs(TreeNode root,String s){
        //1.递归终止条件,到达叶节点
        if(root.left==null && root.right==null){
            ans.add(s);
            return;
        }
        //单层逻辑
        if(root.left!=null)dfs(root.left,s+"->"+root.left.val);
        if(root.right!=null)dfs(root.right,s+"->"+root.right.val);
    }
}

思路分析

  • 这里特别像字母的排列组合,所以我们可以使用回溯算法解决
  • 其次就是他要求从根节点到叶子节点,我们很容易想到深搜
  • 终止条件:到达叶子节点,将当前路径加入答案
  • 单层逻辑:先判断当前节点,而后向下遍历

7.16二叉树左叶子的和

在这里插入图片描述
分析

  • 左叶子:是父节点的左儿子,且没有左右子节点的节点
  • 遍历:找出符合要求的相加即可
class Solution {
    static int sum=0;
    public int sumOfLeftLeaves(TreeNode root) {
        sum=0;
        dfs(root);
        return sum;
    }
    //对整棵树进行遍历,将符合要求的节点的值相加
    public static void dfs(TreeNode root){
        if(root==null)return;
        if(root.left!=null && (root.left.left==null && root.left.right==null)){
            sum=sum+root.left.val;
        }
        dfs(root.left);
        dfs(root.right);
    }
}

7.17找树左下角的值

在这里插入图片描述
思路分析

层序遍历选择最后一层的第一个值

class Solution {
    List<List<Integer>> ans=new ArrayList<>(); 
    public int findBottomLeftValue(TreeNode root) {
        if(root==null)return 0;
        Deque<TreeNode> q=new ArrayDeque<>();
        q.offer(root);
        while(!q.isEmpty()){
            List<Integer> level=new ArrayList<>();
            int size=q.size();
            for(int i=0;i<size;i++){
                TreeNode t=q.poll();
                level.add(t.val);
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
            }
            ans.add(level);
        }
        return ans.get(ans.size()-1).get(0);
    }
}

7.18 路径总和

在这里插入图片描述

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null)return false;
        targetSum=targetSum-root.val;
        if(root.left==null && root.right==null)return  targetSum==0;
        return (root.left!=null && hasPathSum(root.left,targetSum)) ||
        (root.right!=null && hasPathSum(root.right,targetSum));
    }
}

7.19从中序后序序列构造二叉树

在这里插入图片描述

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        TreeNode root=buildTree(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
        return root;
    }
    public static TreeNode buildTree(int[] in ,int ins,int ine,int[] po,int pos,int poe){
        //递归终止条件
        if(pos>poe)return null;
        //单层逻辑
        int rootval=po[poe];
        int index=0;//查找中序中根节点位置
        for(int i=ins;i<=ine;i++){
            if(in[i]==rootval){
                index=i;
                break;
            }
        }
        TreeNode root=new TreeNode(rootval);
        int leftsize=index-ins;//1
        root.left=buildTree(in,ins,index-1,po,pos,pos+leftsize-1);
        root.right=buildTree(in,index+1,ine,po,pos+leftsize,poe-1);
        return root;
    }
}

7.20最大二叉树

在这里插入图片描述

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        TreeNode root=build(nums,0,nums.length-1);
        return root;
    }
    public static TreeNode build(int[] nums,int l,int r){
        if(l>r)return null;
        int max=nums[l],index=l;//记录当前数组的最大值及序号
        //寻找最大值及其序号
        for(int i=l;i<=r;i++){
            if(nums[i]>max){
                max=nums[i];
                index=i;
            }
        }
        TreeNode root=new TreeNode(max);
        root.left=build(nums,l,index-1);
        root.right=build(nums,index+1,r);
        return root;
    }
}

7.21合并二叉树

在这里插入图片描述

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        return dfs(root1,root2);
    }
    public TreeNode dfs(TreeNode root1,TreeNode root2){
        //递归终止条件
        if(root1==null)return root2;
        if(root2==null)return root1;
        root1.val+=root2.val;
        root1.left=dfs(root1.left,root2.left);
        root1.right=dfs(root1.right,root2.right);
        return root1;
    }
}

7.22BST中的搜索

在这里插入图片描述

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        //递归终止条件
        if(root==null)return null;
        //单层逻辑
        if(root.val==val)return root;
        else if(val<root.val)return searchBST(root.left,val);
        else return searchBST(root.right,val);
    }
}

7.23验证二叉搜索树**

在这里插入图片描述

class Solution {
    //使用中序遍历进行操作
    private static long pre;
    public boolean isValidBST(TreeNode root) {
        pre=Long.MIN_VALUE;
        return check(root);
       
    }
    public static boolean check(TreeNode root){
      
        if(root==null)return true;
        if(!check(root.left))return false;
        
        if(root.val<=pre)return false;
        pre=root.val;

        return check(root.right); 

    }
}

7.24二叉搜索树的绝对差

在这里插入图片描述

class Solution {
    public static List<Integer> ans=new ArrayList<>();
    public int getMinimumDifference(TreeNode root) {
        ans.clear();
        dfs(root);
        int min=0x3f3f3f3f;
        for(int i=1;i<ans.size();i++){
            min=Math.min(min,ans.get(i)-ans.get(i-1));
        }
        return min;

    }
    public static void dfs(TreeNode root){
        if(root==null)return;
        dfs(root.left);
        ans.add(root.val);
        dfs(root.right);
    }
}

7.25二叉搜索树中的众数**

在这里插入图片描述

class Solution {
    //中序遍历等同于遍历一个有序数组
    static List<Integer> ans=new ArrayList<>();
    static int maxc=0;//记录最大长度
    static int curc=0;//记录当前遍历数的长度
    static int last;//记录上一个值
    public int[] findMode(TreeNode root) {
        ans.clear();
        maxc=0;
        curc=0;
        last=root.val;
        dfs(root);
        return ans.stream().mapToInt(Integer::intValue).toArray();

    }
    public static void dfs(TreeNode root){
        if(root==null)return;
        dfs(root.left);
        if(curc==0 || root.val==last){//curc为0(特判),当前值与上一个相等
            last=root.val;
            curc++;
        }else{
            last=root.val;
            curc=1;
        }
        //长度大于目前最大长度
        if(curc>maxc){
            //更新以前的数
            ans.clear();
            maxc=curc;
            ans.add(last);
        }else if(curc==maxc){
            ans.add(last);
        }
        dfs(root.right);

    }
}

7.26二叉搜索树中最近公共祖先

在这里插入图片描述

lass Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        return dfs(root,q,p);
            }
    public static TreeNode dfs(TreeNode root,TreeNode p,TreeNode q){
        //递归终止条件
        if(root==null || root==p || root==q)return root;
        TreeNode left=dfs(root.left,p,q);
        TreeNode right=dfs(root.right,p,q);
        //三种情况判断
        if(left!=null && right!=null)return root;
        if(left==null)return right;
        return left;
    }
}

7.27二叉搜索树的插入

在这里插入图片描述

//找到符合要求的叶子节点插入
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root==null)return new TreeNode(val);
        if(root.val>val)root.left=insertIntoBST(root.left,val);
        else root.right=insertIntoBST(root.right,val);

        return root;

    }
}

7.28二叉搜索树的删除**

在这里插入图片描述

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root==null)return root;
        if(root.val==key){
            if(root.left==null){//叶子节点
                return root.right;
            }else if(root.right==null){
                return root.left;
            }else{//左右都不为空
                //找到右子树最左边的节点
                TreeNode cur=root.right;
                while(cur.left!=null){
                    cur=cur.left;
                }
                cur.left=root.left;
                root=root.right;
                return root;
            }
        }
        if(root.val>key)root.left=deleteNode(root.left,key);
        else root.right=deleteNode(root.right,key);
        return root;
    }
}

7.29修剪二叉搜索树**

在这里插入图片描述

class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root==null)return null;
        if(root.val<low)return trimBST(root.right,low,high);
        if(root.val>high)return trimBST(root.left,low,high);
        root.left=trimBST(root.left,low,high);
        root.right=trimBST(root.right,low,high);
        return root;
    }
}

7.30将有序数组转换为二叉搜索树

在这里插入图片描述

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return build(nums,0,nums.length-1);

    }
    public static TreeNode build(int[] nums,int l,int r){
        if(l>r)return null;
        int mid=l+r>>1;
        TreeNode root=new TreeNode(nums[mid]);
        root.left=build(nums,l,mid-1);
        root.right=build(nums,mid+1,r);
        return root;
    }
}

7.31 将二叉搜索树转换为累加树

在这里插入图片描述

class Solution {
    public static int sum;
    public TreeNode convertBST(TreeNode root) {
        sum=0;
        dfs(root);
        return root;

    }
    public static void dfs(TreeNode root){
        if(root==null)return;
        dfs(root.right);
        sum=sum+root.val;
        root.val=sum;
        dfs(root.left);

    }
}

8.回溯算法

8.0算法总结

组合问题

  • N个数里面按一定规则出k个数的集合

  • 题目:1,2,3,4,5

  • 代码模板

    void backtracking(参数) {
    //参数:start(遍历开始未知),u(遍历到第几位),tar(目标值),其他数
    
        if (终止条件) {
            存放结果;
            return;
        }
        for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
            处理节点;
            backtracking(路径,选择列表); // 递归
            回溯,撤销处理结果
        }
    }
    
  • 类型总结

    1. 从同一个集合中有放回的抽取(可重复使用一个数字)[4]
    2. 从同一个集合中无放回的抽取(每个数字使用一次):[1,2,5]
    3. 多个集合中每个选取一个进行组合:[3]
  • 技巧总结

    • 类型1,2:一般有start(从那个位置遍历,该参数实际上也有去重功能),1取同位置(i),2取下一个位置 (i+1)
    • 类型3:不需要start,因为多个集合*取组合,各个集合之间相互不影响
    • 求和问题:先排序,后爆搜
    • 去重(组合总和II)
      同层去重:candidates[i] == candidates[i - 1] && used[i - 1] == false(前一个树枝使用过该数)
      树枝去重:candidates[i] == candidates[i - 1] && used[i - 1] == true(同一树枝的前面节点使用过)
      在这里插入图片描述
  • 分割问题

  • 子集问题

  • 排列问题

  • 棋盘问题

8.1组合问题

在这里插入图片描述

class Solution {
    public static List<Integer> path=new ArrayList<>();
    public static List<List<Integer>> ans=new ArrayList<>();
    public static int k,n;
    public List<List<Integer>> combine(int n, int k) {
        ans.clear();
        path.clear();
        this.n=n;
        this.k=k;
        dfs(0,1);
        return ans;
    }
    public static void dfs(int p,int start){//startfor循环起始位置
        //递归终止条件
        if(p==k){
            List<Integer> tmp=new ArrayList<>(path);
            ans.add(tmp);
            return;
        }
        //单层逻辑
        for(int i=start;i<=n;i++){
                path.add(i);
                dfs(p+1,i+1);//为了保证不重复下此遍历重i+1开始
                path.remove(path.size()-1);   
        }
    }
}

8.2组合总和III

在这里插入图片描述

class Solution {
    static List<Integer> path=new ArrayList<>();
    static List<List<Integer>> ans=new ArrayList<>();
    public List<List<Integer>> combinationSum3(int k, int n) {
        path.clear();
        ans.clear();
        dfs(1,n,k);
        return ans;
    }
    public static void dfs(int start,int n,int k){
        if(n==0){//和达到要求
            if(k==0)ans.add(new ArrayList<>(path));
            return;
        }
        for(int i=start;i<=9;i++){
            if(n>=i){
                path.add(i);
                dfs(i+1,n-i,k-1);//k--为什么是错的
                path.remove(path.size()-1);
            }
    }        
    }
}

8.3电话号码的组合

在这里插入图片描述

class Solution {
    static List<String> ans=new ArrayList<>();
    static String[] strs={
        "","","abc","def",
        "ghi","jkl","mno",
        "pqrs","tuv","wxyz"
    };
    public List<String> letterCombinations(String digits) {
        ans.clear();
        if(digits.isEmpty())return ans;
        dfs(digits,0,"");
        return ans;
    }
    static void dfs(String digits,int u ,String path){//遍历到第几位了
        if(u==digits.length()){
            ans.add(path);//并非使用全局变量记录,所以不需要从新构造
            return;
        }
        char[] chs=strs[digits.charAt(u)-'0'].toCharArray();
        for(char c:chs){
            dfs(digits,u+1,path+c);//这里传的是一个参数所以不需要恢复现场
        }
    }
}

8.4 组合总和

在这里插入图片描述

class Solution {
    public static List<List<Integer>> ans=new ArrayList<>();
    public static List<Integer> path=new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        path.clear();
        ans.clear();
        Arrays.sort(candidates);
        dfs(candidates,target,0);
        return ans;
    }
    public static void dfs(int[] can,int target,int start){
        if(target<0)return;
        if(target==0){
            ans.add(new ArrayList<>(path));//符合要求的加入集合
            return;
        }
        for(int i=start;i<can.length;i++){
            path.add(can[i]);
            dfs(can,target-can[i],i);//不用下一个,取这一个即可
            path.remove(path.size()-1);
        }
    }
}

8.5组合总和II

在这里插入图片描述

class Solution {
    public static List<Integer> path=new ArrayList<>();
    public static List<List<Integer>> ans=new ArrayList<>();
    public static boolean[] st=new boolean[110];
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        path.clear();
        ans.clear();
        Arrays.sort(candidates);
        dfs(0,target,candidates);
        return ans;

    }
    public static void dfs(int start,int target ,int[] can){
        if(target==0){
            ans.add(new ArrayList<>(path));
            return;
        }
        for(int i=start;i<can.length;i++){
            if(i!=0 && can[i]==can[i-1] && st[i-1]==false)continue;
            
            if(target>=can[i]){
                path.add(can[i]);
                st[i]=true;
                dfs(i+1,target-can[i],can);
                st[i]=false;
                path.remove(path.size()-1);

            }
            
        }
    }
    
}

9.贪心算法

10.动态规划

10.1斐波那契数

在这里插入图片描述

class Solution {
    
    public int fib(int n) {
        if(n==1)return 1;
        if(n==0)return 0;
        int a=0,b=1,c=0;
        for(int i=2;i<=n;i++){
            c=a+b;
            a=b;
            b=c;
        }
        return c;

    }
}

10.2爬楼梯

在这里插入图片描述

class Solution {
    public int climbStairs(int n) {
        if(n<=2)return n;
        int[] dp=new int[n+1];
        //值得初始化
        dp[1]=1;
        dp[2]=2;
        for(int i=3;i<=n;i++)dp[i]=dp[i-1]+dp[i-2];
        return dp[n];
    }
}

10.3使用最小花费爬楼梯

在这里插入图片描述

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n=cost.length;
        int[] dp=new int[n+1]; 
        dp[0]=0;
        dp[1]=0;//可以选择从1阶或2阶爬
        for(int i=2;i<=n;i++){
            dp[i]=Math.min(dp[i-2]+cost[i-2],dp[i-1]+cost[i-1]);
        }
        return dp[n];

    }
}

10.4不同路径

在这里插入图片描述

class Solution {
    public int uniquePaths(int m, int n) {
        if(n<=1 || m<=1)return 1;
        int[][] dp=new int[n][m];
        //值得初始化
        for(int i=1;i<m;i++)dp[0][i]=1;
        for(int i=1;i<n;i++)dp[i][0]=1;
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++)dp[i][j]=dp[i-1][j]+dp[i][j-1];
        }
        return dp[n-1][m-1];
    }
}

10.5 不同路径II

在这里插入图片描述

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int rs=obstacleGrid.length;
        int cs=obstacleGrid[0].length;        
        int[][] dp=new int[rs][cs];
        //值得初始化
        for(int i=0;i<rs;i++){
            if(obstacleGrid[i][0]==0){
                dp[i][0]=1;
            }else{
                break;
            }
        }
        for(int i=0;i<cs;i++){
            if(obstacleGrid[0][i]==0){
                dp[0][i]=1;
            }else{
                break;
            }
        }
        for(int i=1;i<rs;i++){
            for(int j=1;j<cs;j++){
                if(obstacleGrid[i][j]==0){
                    dp[i][j]=dp[i-1][j]+dp[i][j-1];
                }
            }
        }
        return dp[rs-1][cs-1];

    }
}

10.6不同得二叉搜索树

在这里插入图片描述

class Solution {
    public int numTrees(int n) {
        int[] dp=new int[n+1];
        dp[0]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                dp[i]+=dp[j-1]*dp[i-j];
            }
        }
        return dp[n];


    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值