力扣java刷题学习(代码随想录学习)1

刷题目录

数组

704.二分查找

class Solution {
    public int search(int[] nums, int target) {
        /* 确保不会出现target目标值超出范围 */
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        /*解的是[l r]都是闭区间的情况,l == r 是有意义的。*/
        int left = 0;
        int right = nums.length - 1;
        /*都是闭区间用<=*/
        while(left <= right){
         int mid = (left + right) / 2;
         if(nums[mid] == target){
             return mid;
         }
         else if(nums[mid] > target){
             right = mid - 1; /*闭区间必须-1,因为会在while判断的时候再判断一次right,重复判断。*/
         }
         else{
             left = mid + 1;
         }
        }
        return -1;
    }
}

左闭右开理解:
左闭右开






27.移除元素

/*这是我自己的想法,两个指针从头尾双寻找,最后返回尾指针+1(数组是从0开始的,长度是算的总长度)*/
class Solution {
    public int removeElement(int[] nums, int val) {
        int finalLen = nums.length - 1;//切记一定要 -1,如果不 -1后面运行会报错,超出数组范围。
        int originalLen = 0;
       while(originalLen <= finalLen){
           if(nums[originalLen] != val)
               originalLen++;
           else if(nums[originalLen] == val && nums[finalLen] != val){
                nums[originalLen] = nums[finalLen];
                finalLen--;
                originalLen++;
            }
           else if(nums[originalLen] == val && nums[finalLen] == val)
            finalLen--;
       }
       return finalLen + 1;
    }
}

快慢指针理解:
快慢指针

class Solution {
    public int removeElement(int[] nums, int val) {
        // 快慢指针
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}






977. 有序数组的平方

class Solution {
    public int[] sortedSquares(int[] nums) {
        /*暴力破解法*/
        for(int i = 0; i < nums.length; i++)
        {
            nums[i] = nums[i] * nums[i];
        }
        Arrays.sort(nums);
        return nums;
    }
}
/* 双指针方法 */
class Solution {
    public int[] sortedSquares(int[] nums) { 
        int i = nums.length - 1;
        int[] finalArray = new int[i + 1];
        int head = 0 , tail  = i;
        int oneSqu = 0 , twoSqu = 0;
        
        while(head <= tail){
            oneSqu = nums[head] * nums[head];
            twoSqu = nums[tail] * nums[tail];
            if(oneSqu < twoSqu){
                finalArray[i] = twoSqu;
                tail--;
                i--;
            }
            else{
                finalArray[i] = oneSqu;
                head++;
                i--;
            }
        } 
        return finalArray;
    }
}

双指针法理解:
双指针法





209.长度最小的子数组

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
    //滑动窗口思想解决问题。
        int result  = Integer.MAX_VALUE;
        int sum = 0; //数总和
        int i = 0; 	//起始指针
        int subLength = 0;
        for(int j = 0; j < nums.length; j++)  //j代表尾指针
        {
            sum += nums[j];
            while(sum >= target)
            {
                subLength = (j - i + 1);
                result = result < subLength ? result : subLength;
                sum -= nums[i];
                i++;
            }
        }
        if( result == Integer.MAX_VALUE ) //找不到需要返回0
            return 0;
        return result;
    }
}

滑动窗口思想:
请添加图片描述






59.螺旋矩阵II

配图思考
示例为3

class Solution {
//本题主打一个边界问题,此垃圾循环边界是旧边的最后一个,即新边的第一个。
    public int[][] generateMatrix(int n) {
        int nums[][] = new int[n][n];
        int k = 1;
        for(int i = 0; i < n; i++)
        {
            int m = n - 1 - i;//正向横
            int h = n - 1 - i;//正向纵
            int a = n - 1 - i;//反向横
            int b = n - 1 - i;//反向纵
            if(k == n*n)
            {
                nums[i][n-1-i] = k;
                break;
            }
            for(int j = i;j < n-1-i; j++)
            {
                nums[i][j] = k;
                k++;
                m--;
            }
            for(int j = i;j < n-1-i; j++)
            {
                nums[j][n-1-i] = k;
                k++;
                h--;
            }
            for(int j = n-1-i;j > i; j--)
            {
                nums[n-1-i][j] = k;
                k++;
                a--;
            }
            for(int j = n-1-i;j > i; j--)
            {
                nums[j][i] = k;
                k++;
                b--;
            }   
        }
        return nums;
    }
}






链表

首先要学会如何建立链表

public class ListNode {
    // 结点的值
    int val;
    // 下一个结点
    ListNode next;
    // 节点的构造函数(无参)
    public ListNode() {
    }
    // 节点的构造函数(有一个参数)
    public ListNode(int val) {
        this.val = val;
    }
    // 节点的构造函数(有两个参数)
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

203.移除链表元素

class Solution {
    public ListNode removeElements(ListNode head, int val) {
			//不是if的原因是为了应对整个链全是要删除的情况。
        while (head != null && head.val == val) { // 注意这里不是if
            head = head.next;
        }
        ListNode replace = head;
        while(replace != null){
        //replace的下一个不能为空先判断的原因是,如果是空next.val读取不到数据,因为下一个指针是空。
        //head在最开始已经排除了是要删除的对象,所以可以这么考虑。
            if(replace.next !=null && replace.next.val == val){
                replace.next = replace.next.next;
            }
            else
            replace = replace.next;
        }
        return head;
    }
}


/*设置虚拟头结点方法*/
class Solution {
    public ListNode removeElements(ListNode head, int val) {

        ListNode dummyHead = new ListNode(); // 设置一个虚拟头结点
        dummyHead.next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode cur = dummyHead;
        while (cur.next != null) {
            if(cur.next.val == val) {
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        head = dummyHead.next;
        return head;
    }
}






707.设计链表

class ListNode {
    int val;
    ListNode next;
    ListNode(){}
    ListNode(int val) {
        this.val=val;
    }
}
class MyLinkedList {
    int size; //链表下标
    ListNode head;//虚拟链表头结点。注意:可以吧虚拟表头理解为下标为-1。
    
    public MyLinkedList() {//初始化链表
        size = 0;
        head = new ListNode(0);
    }
    
    public int get(int index) {得到下标为index位置的数值,不存在则返回-1
        ListNode searchNum = head.next;
        if(index >= size)
            return -1;
        for(int i = 0; i < index; i++)
            searchNum = searchNum.next;
        return searchNum.val;
    }
    
    public void addAtHead(int val) {//添加头结点
     	addAtIndex(0,val);
       /* ListNode newNode = new ListNode(val);
        if(head.next == null){
            head.next = newNode;
            size++;
        }
        else{
            newNode.next = head.next;
            head.next = newNode;
            size++;
        }*/
    }
    
    public void addAtTail(int val) {//添加尾结点
    	addAtIndex(size,val);
       /* ListNode replace = head;
        ListNode newNode = new ListNode(val);
        newNode.next = null;
        while(replace.next != null){
            replace = replace.next;
        }
        replace.next = newNode;
        size++;*/
    }
    
    public void addAtIndex(int index, int val) {//在下标位置添加节点
        if(index <= size){
            //if(index == size)
                //addAtTail(val);
            //else{
                ListNode newNode = new ListNode(val);
                ListNode replace = head;
                for(int i = 0;i < index;i++){
                    replace = replace.next;
                }
                newNode.next = replace.next;
                replace.next = newNode;
                size++;
            //}
        } 
    }
    
    public void deleteAtIndex(int index) {//删除下标为index的节点
        if(index < size){
            ListNode replace = head;
            for(int i = 0;i < index;i++){
                replace = replace.next;
            }
            replace.next = replace.next.next;
            size--;     
        }
    }
}






206.反转链表

class Solution {
//双指针的写法
   public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        ListNode temp = null;//中转节点
        while (cur != null) {
            temp = cur.next;// 保存下一个节点
            cur.next = prev;
            prev = cur;
            cur = temp;
        }
        return prev;
    }
}






24. 两两交换链表中的节点

class Solution {
//设置一个虚拟头结点好做题
    public ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode cur = dummyHead;
        ListNode tmp;//临时节点
        //思路:临时节点=头结点,虚拟头指向第二个节点,临时节点指向第三个节点,第二个节点指向临时节点
        while(cur.next != null && cur.next.next !=null){
            tmp = cur.next;
            cur.next = tmp.next;
            tmp.next = cur.next.next;
            cur.next.next = tmp;

            cur = cur.next.next;
        }
        return dummyHead.next;
    }
}






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

class Solution {
    //考虑双临时节点情况
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode firstNode = dummyHead;
        ListNode nextNode = head;
        int num = 0;
        while(nextNode != null){
            num++;
            nextNode = nextNode.next;
        }
        nextNode = head;
        for(int i = 1;i < num-n+1;i++){
            firstNode = nextNode;
            nextNode = nextNode.next;
        }
        firstNode.next = nextNode.next;
        return dummyHead.next;
    }
}






02.07. 链表相交 同160.链表相交

public class Solution {
    //注意交点不是数值相等,而是指针相等
    /*自己写的感觉不太彳亍,全是循环,主要思路是如果相交的话,后面长度是一样的,那么有差距的就是前面
    求出长度差,长的部分从长度差后开始找,找到了地址相同就是相交,找不到就是没交点。*/
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode nodeA = headA;
        ListNode nodeB = headB;
        ListNode interSect = null;//存放交点
        int numA = 0,numB = 0;
        int a = 0;
        /* 求长度*/
        while(nodeA!=null){
            numA++;
            nodeA = nodeA.next;
        }
         while(nodeB!=null){
            numB++;
            nodeB = nodeB.next;
        }
        /*把长的链表的开始搜索节点向后移动*/
        nodeA = headA;
        nodeB = headB;
        if(numA > numB){
            a = numA - numB;
            while(a!=0){
            nodeA = nodeA.next;
            a--;
            }
        }
        else{
            a = numB - numA;
            while(a!=0){
            nodeB = nodeB.next;
            a--;
            }
        }
        //找交点
        while(nodeA!=null && nodeB!=null){
            if(nodeA == nodeB){
                interSect = nodeA;
                break;
            }
            nodeA = nodeA.next;
            nodeB = nodeB.next;
        }
        return interSect;
    }
}






142.环形链表II

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {// 有环
                ListNode index1 = fast;
                ListNode index2 = head;
                // 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

判断是否有环
判断是否有环





哈希表

一般哈希表都是用来快速判断一个元素是否出现集合里

242.有效的字母异位词

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];

        for (int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;     // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
        }

        for (int i = 0; i < t.length(); i++) {
            record[t.charAt(i) - 'a']--;
        }
        
        for (int count: record) {
            if (count != 0) {               
                return false;
            }
        }
        return true;                       
    }
}

因为判断的是小写字母,所以设计一个26长度的哈希表就可以,字母出现一次对应位置+1,在另一个字符串出现一次就-1,最后只有整个数组是0才是正确的。






349. 两个数组的交集

import java.util.HashSet;
import java.util.Set;
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        int[] hash = new int[1005];
        Set<Integer> resSet = new HashSet<>();//为了不输出重复值使用哈希表来装
        for(int num : nums1){
            hash[num] = 1;
        }
        for (int num : nums2) { // nums2中出现话,result记录
            if (hash[num] == 1) {
                resSet.add(num);
            }
        }
        return resSet.stream().mapToInt(x -> x).toArray();//将结果集合转为数组
    }
}






202.快乐数

class Solution {
        //求和函数
    public int getNum(int n){
        int sum = 0;
        int i = 0;
        while(n!=0){
            i = n % 10;
            sum += i*i;
            n = n / 10;
        }
        return sum;
    }
    /*
    	主要思路在于无限循环,证明一定会出现之前已经出现过的数,所以判断哈希表内是否同样的数有一次出现即可
    */
    public boolean isHappy(int n) {
        Set<Integer> record = new HashSet<>();
        int sum = n;
        while(true){
            record.add(sum);
            sum = getNum(sum);
            if(sum ==1){
                break;
            }
            //contains用于判断集合中是否包含某个元素
            if(record.contains(sum)){
                return false;
            }
        }
        return true;
    }
}






1. 两数之和

class Solution {
/*
	从头遍历一遍因为要存两个关键数据,所以使用map,在map中找不到的话,就把遍历过的数据放进map中,然后再向后遍历,
	因为是往后遍历的,所以找到的那个数据下标一定是大的。
*/
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> record = new HashMap<>();
        int[] underIndex = new int[2];
        for(int i =0; i< nums.length; i++){
            int n = target - nums[i];
            if(record.containsKey(n) ){
                underIndex[1] = i;
                underIndex[0] = record.get(n);
                return underIndex;
            }
            record.put(nums[i],i);

        }
        
        return underIndex;
    }
}






454.四数相加II

class Solution {
/*
	主要思路是要两两计算统计,ab的和,然后再计算cd的和。
*/
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer, Integer> map = new HashMap<>();
        int temp;
        int res = 0;
        //统计两个数组中的元素之和,同时统计出现的次数,放入map
        for (int i : nums1) {
            for (int j : nums2) {
                temp = i + j;
                if (map.containsKey(temp)) {
                    map.put(temp, map.get(temp) + 1);
                } 
                else {
                    map.put(temp, 1);
                }
            }
        }
        //统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数
        for (int i : nums3) {
            for (int j : nums4) {
                temp = i + j;
                if (map.containsKey(0 - temp)) {
                    res += map.get(0 - temp);
                }
            }
        }
        return res;
    }
}






383. 赎金信

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] hash = new int[26];
        for(int i = 0;i < magazine.length();i++){
            hash[magazine.charAt(i) - 'a']++;
        }
        for(int i = 0;i < ransomNote.length();i++){
            hash[ransomNote.charAt(i) - 'a']--;
        }
        int index = 0;
        for(int i = 0;i < 26;i++){
            if(hash[i] < 0){
                index++;
            }
        }
        if(index > 0)
            return false;
        else
            return true;
    }
}






15.三数之和

class Solution {
//a = nums[i],b = nums[left],c = nums[right]。
//排序的好处:更方便的去重,可以直接考虑上一个出现过的数字。
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for(int i = 0;i < nums.length;i++){
            if(nums[i] > 0)
                return result;
            if (i > 0 && nums[i] == nums[i - 1]) {  // 去重a
                continue;
            }
            int left = i + 1;
            int right = nums.length - 1;
            while(right > left){
            // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
                int sum = nums[i] + nums[right] + nums[left];
                if(sum > 0){
                    right--;
                }
                else if(sum < 0){
                    left++;
                }
                else{
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    //去重b c
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;/*可写可不写,因为
                    已经对数组进行了排序,只对一边进行去重就足以让sum不等于0了*/
                    right--;
                    left++;
                }
            }
        }
        return result;
    }
}






18.四数之和

class Solution {
//主要思路三数之和相同,外层再加一个for循环,然后在新的循环内判断剪枝(到什么时候就该停止,后面必不可能存在)去重。
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for(int k = 0;k < nums.length;k++){
            if(nums[k] >= 0 && nums[k] > target)
                break;
            if(k > 0 && nums[k] == nums[k-1])
                continue;
            for(int i = k+1;i < nums.length; i++){
                if(nums[i] + nums[k] > target && nums[i] + nums[k] >=0)
                    break;
                if(i > k+1 && nums[i] ==nums[i-1])
                    continue;
                int left = i + 1;
                int right = nums.length - 1;
                while(right > left){
                    int sum = nums[k] + nums[i] + nums[left] + nums[right];
                    if(sum > target)
                        right--;
                    else if(sum < target)
                        left++;
                    else{
                        result.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));
                        
                        while(right > left && nums[left] == nums[left+1]) left++;
                        while(right > left && nums[right] == nums[right-1]) right--;
                        right--;
                        left++;
                    } 
                }
            }
        }
        return result;
    }
}






字符串

344.反转字符串

class Solution {
//双指针
    public void reverseString(char[] s) {
        char temp;
        int left = 0;
        int right = s.length - 1;
        while(right > left){
            temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
}






541. 反转字符串II

//先转成字符串,设计一个移动指针,来完成问题。
class Solution {
    public char[] reverseChar(char[] s, int left ,int right) {
        char temp;
        while(right > left){
            temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
        return s;
    }
    public String reverseStr(String s, int k) {
        char[] schar = s.toCharArray();
        if(s.length() < k){
            schar =  reverseChar(schar,0,s.length()-1);
            return new String(schar);
        }
        else{
            int j = 1;
            int sum = s.length() - j;
           while(true){
               if((j % (2*k)) == 0){
                   schar = reverseChar(schar,j - (2*k),j - k -1);
                   sum = s.length() - j; 
                   //一定要在反转字符串后再判断长度问题,如果再外面判断会出现j正在下一个2k区间内移动就给退出。
                    if(sum < (2*k))
                        break;
               }
               j++;
           }
           if(sum < (2*k) && sum >= k){
               schar = reverseChar(schar,j,j + k -1);
           }
           else if(sum < k){
               schar = reverseChar(schar,j,s.length()-1);
           }
        }
        return new String(schar);
    }
}
//题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
//这个更好
class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray();
        for(int i = 0; i < ch.length; i += 2 * k){
            int start = i;
            //这里是判断尾数够不够k个来取决end指针的位置
            int end = Math.min(ch.length - 1, start + k - 1);
            while(start < end){
                char temp = ch[start];
                ch[start] = ch[end];
                ch[end] = temp;

                start++;
                end--;
            }
        }
        return new String(ch);
    }
}






剑指Offer 05.替换空格

class Solution {
//逐个替换方法
    public static String replaceSpace(String s) {
        if (s == null) {
            return null;
        }
        //选用 StringBuilder 单线程使用,比较快,选不选都行
        StringBuilder sb = new StringBuilder();
        //使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制
        for (int i = 0; i < s.length(); i++) {
            //s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
            //if (" ".equals(String.valueOf(s.charAt(i)))){}
            if (s.charAt(i) == ' ') {
                sb.append("%20");
            } else {
                sb.append(s.charAt(i));
            }
        }
        return sb.toString();
    }
}






151.翻转字符串里的单词

class Solution {
    public String reverseWords(String s) {
        s = removeExtraSpaces(s.toCharArray());
        char[] sb = s.toCharArray();
        StringBuilder result = new StringBuilder();
        int j = sb.length -1;
		//用一个新字符串往里面一个个填写单词(也可以用s.charAt()写,不需要在申请一个字符串数组)
        for(int i = sb.length - 1;i >=0;i--){
            if(sb[i] ==' '){
                int k = i + 1;
                while(k <= j){
                    result.append(sb[k++]);
                }
                result.append(' ');
                j = i-1;
            }
            if(i == 0){
                int k = i ;
                while(k <= j){
                    result.append(sb[k++]);
                }
            }
        }

        return result.toString();
    }
    public String removeExtraSpaces(char[] s) {
        //去除所有空格并在相邻单词之间添加空格, 快慢指针。
        int slow = 0;   
        for (int i = 0; i < s.length; i++) { 
            if(s[i] != ' '){
                if(slow > 0){
                //给新单词后面加上空格
                    s[slow++] = ' ';
                }
                //重新在字符串内写单词
                while(i < s.length && s[i] !=' '){
                    s[slow++] = s[i++];
                }
            }
        }
        return new String(s,0,slow); //slow的大小即为去除多余空格后的大小。
    }
}






剑指Offer58-II.左旋转字符串

class Solution {
//简单版本
    public String reverseLeftWords(String s, int n) {
        int len=s.length();
        StringBuilder sb=new StringBuilder();
        for(int i = n;i < s.length();i++)
            sb.append(s.charAt(i));
        for(int i = 0;i < n;i++)
            sb.append(s.charAt(i));
        return sb.toString();
    }
}
//解法二:空间复杂度:O(1)。用原始数组来进行反转操作
//思路为:先整个字符串反转,再反转前面的,最后反转后面 n 个
class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] chars = s.toCharArray();
        reverse(chars, 0, chars.length - 1);
        reverse(chars, 0, chars.length - 1 - n);
        reverse(chars, chars.length - n, chars.length - 1);
        return new String(chars);
    }

    public void reverse(char[] chars, int left, int right) {
        char temp;
        while (left < right) {
            temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;
            left++;
            right--;
        }
    }
}






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

class Solution {
    public int strStr(String haystack, String needle) {
        if(haystack.length() == 0 || needle.length() == 0)
            return -1;
        int[] next = nextArray(needle);
        int j = 0;
        int i = 0;
        while(i < haystack.length()){
            while(j < needle.length() && i < haystack.length() && haystack.charAt(i) == needle.charAt(j)){
                j++;
                i++;
            }
            if(j == needle.length())
                break;
            else if(j!=0)
                j = next[j - 1];
            else if(j == 0)
                i++;
        }
        if(j == needle.length())
            return i - j;
        else
            return -1;
        
    }
//next数组,通过kmp算法完成next数组的初始化,当前指针的前一个数组位置是该返回的字符串下标。
    public int[] nextArray(String s){
            int[] next = new int[s.length()];
            int j = 0;
            for(int i = 1; i < s.length();i++){
                while(j > 0 && s.charAt(j) != s.charAt(i))
                    j = next[j-1];
                if(s.charAt(j) == s.charAt(i))
                    j++;
                next[i] = j;
            }
        return next;
    }

}






459.重复的子字符串

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int[] next = nextArray(s);
        int i = s.length() - next[next.length - 1];
        //不可以为0,如果是0的话i为s的长度。![请添加图片描述](https://img-blog.csdnimg.cn/9ae66d3b9ea4477d97cccc0b064888d1.png)

        if(next[next.length - 1] !=0 && (s.length() % i) == 0)
            return true;
        return false;
    }
    public int[] nextArray(String s){
            int[] next = new int[s.length()];
            int j = 0;
            for(int i = 1; i < s.length();i++){
                while(j > 0 && s.charAt(j) != s.charAt(i))
                    j = next[j-1];
                if(s.charAt(j) == s.charAt(i))
                    j++;
                next[i] = j;
            }
        return next;
    }
}

如何获得最小重复子串:
请添加图片描述
简单推理
请添加图片描述





双指针法

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

public ListNode removeNthFromEnd(ListNode head, int n){
    ListNode dummyNode = new ListNode(0);
    dummyNode.next = head;

    ListNode fastIndex = dummyNode;
    ListNode slowIndex = dummyNode;

    //只要快慢指针相差 n 个结点即可
    for (int i = 0; i < n  ; i++){
        fastIndex = fastIndex.next;
    }

    while (fastIndex.next != null){
        fastIndex = fastIndex.next;
        slowIndex = slowIndex.next;
    }

    //此时 slowIndex 的位置就是待删除元素的前一个位置。
    //具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
    slowIndex.next = slowIndex.next.next;
    return dummyNode.next;
}






栈与队列

232.用栈实现队列

//用两个栈实现
class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>(); // 负责进栈
        stackOut = new Stack<>(); // 负责出栈
    }
    
    public void push(int x) {
        stackIn.push(x);
    }
    
    public int pop() {
        dumpstackIn();
        return stackOut.pop();
    }
    
    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.empty() && stackOut.empty();
    }
    private void dumpstackIn(){
        if (!stackOut.empty()) return; 
        while (!stackIn.empty()){
                stackOut.push(stackIn.pop());
        }
    }
}

/**
 * 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();
 */






225. 用队列实现栈

class MyStack {
//只用一个队列实现
    Queue<Integer> queueAll;

    public MyStack() {
        queueAll = new LinkedList<>();
    }
    
    public void push(int x) {
        queueAll.add(x);
        reserveNum();
    }
    
    public int pop() {
       return queueAll.poll();
    }
    
    public int top() {
       return queueAll.peek();
    }
    
    public boolean empty() {
        return queueAll.isEmpty();
    }
    
    //作用是翻转之前所有输入的数据,让最新数据保持在第一位
    public void reserveNum(){
        int i = 1;
        while(i < queueAll.size()){
            queueAll.add(queueAll.remove());
            i++;
        }
    }
}

/**
 * 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();
 */






20. 有效的括号

class Solution {
//使用双端队列
    public boolean isValid(String s) {
        Deque<Character> deque = new LinkedList<>();
        for(int i = 0;i < s.length(); i++){
            if(s.charAt(i) == '(' )     deque.push(')');

            else if(s.charAt(i) == '[') deque.push(']');

            else if(s.charAt(i) == '{') deque.push('}');

            else if(deque.isEmpty() || deque.poll() != s.charAt(i))
                return false;
            
        }
        return deque.isEmpty();
    }
}






1047. 删除字符串中的所有相邻重复项

//使用栈操作
class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> result = new Stack<>();
        int i = 0;
        char ch;
        while(i < s.length()){
            ch = s.charAt(i);
            if(result.empty() || ch != result.peek()){
                result.push(ch);
            }
            else{
                result.pop();
            }
            i++;
        }
        String str = "";
        //剩余的元素即为不重复的元素
        while (!result.empty()) {
            str = result.pop() + str;
        }
        return str;
    }
}
class Solution {
    public String removeDuplicates(String s) {
        // 将 字符串res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        // StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();
        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
            if (top >= 0 && res.charAt(top) == c) {
                res.deleteCharAt(top);
                top--;
            // 否则,将该字符 入栈,同时top++
            } else {
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }
}






150. 逆波兰表达式求值

//思想是使用栈,运算符前两个数字,是使用该运算符计算的。计算后再把数重新放入栈中,找到运算符就计算,重复过程。
class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        int i,sum;
        for(String s : tokens){
            if("+".equals(s)){
                i = stack.pop();
                sum = stack.pop() + i;
                stack.push(sum);
            }
            else if("-".equals(s)){
                i = stack.pop();
                sum = stack.pop() - i; 
                stack.push(sum);
            }
            else if("*".equals(s)){
                i = stack.pop();
                sum = stack.pop() * i; 
                stack.push(sum);
            }
             else if("/".equals(s)){
                i = stack.pop();
                sum = stack.pop() / i; 
                stack.push(sum);
            }
            else{
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }
}






239. 滑动窗口最大值

class Solution {
    class MyQueue{
        Deque<Integer> deque = new LinkedList<>();
        public void pop(int val){
      //弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
      //同时判断队列当前是否为空
            if(!deque.isEmpty() && deque.peek() == val)
                deque.poll();
        }
    //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
    //保证队列元素单调递减
    //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
        public void push(int val){
            while(!deque.isEmpty() && val > deque.peekLast())
                deque.pollLast();
            deque.add(val);
        }
        //队列队顶元素始终为最大值
        public int peek() {
            return deque.peek();
        }
    }
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 1) {
            return nums;
        }
        //计算需要多少空间。
        int len = nums.length - k + 1;
        int[] res = new int[len];
        int num = 0;
        MyQueue result = new MyQueue();
        for(int i = 0;i < k; i++)
            result.push(nums[i]);
        //必须现在外面存一下,然后循环内一定要放在最后,不然会漏一次结果。
        res[num++] = result.peek();
        for(int i = k;i < nums.length;i++){    
            result.pop(nums[i - k]);
            result.push(nums[i]);
            res[num++] = result.peek();
        }
        return res;
    }
}






347.前 K 个高频元素

//基于小顶堆实现,只维护k个数据。
class Solution {
    //key为数组元素值,val为对应出现次数
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        for(int i:nums ){
            if(map.get(i) == null) map.put(i,1);
            else{
                map.put(i,map.get(i) + 1);
            }
        }
        //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
        //出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆)
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
        for(Map.Entry<Integer,Integer> entry1 : map.entrySet()){
            if(pq.size() < k) 
                pq.add(new int[]{entry1.getKey(),entry1.getValue()});
            else if(entry1.getValue() > pq.peek()[1]){
                pq.poll();
                pq.add(new int[]{entry1.getKey(),entry1.getValue()});
            }
        }
        int[] ans = new int[k];
        for(int i=k-1;i>=0;i--){
            ans[i] = pq.poll()[0];
        }
        return ans;
    }
}






二叉树

二叉树的递归遍历

144. 二叉树的前序遍历

/**
 * 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> result = new ArrayList<Integer>();
        traversal(root,result);
        return result;
    }


    public void traversal(TreeNode root,List<Integer> result){
        if(root == null){
            return;
        }
        result.add(root.val);
        traversal(root.left,result);
        traversal(root.right,result);
    }
}

145.二叉树的后序遍历

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        traversal(root,result);
        return result;
    }


    public void traversal(TreeNode root,List<Integer> result){
        if(root == null){
            return;
        }
        
        traversal(root.left,result);
        traversal(root.right,result);
        result.add(root.val);
    }
}

94.二叉树的中序遍历

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        traversal(root,result);
        return result;
    }


    public void traversal(TreeNode root,List<Integer> result){
        if(root == null){
            return;
        }
        
        traversal(root.left,result);
        result.add(root.val);
        traversal(root.right,result);
    }
}






二叉树的迭代遍历

//非递归遍历,因为用的是栈的方式,所以先把右节点装进去,这样才能先把左节点放出来。前序遍历
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        Stack<TreeNode> nodeStack = new Stack<>();
        nodeStack.push(root);
        while(!nodeStack.empty()){
            TreeNode node = nodeStack.pop();
            if(node == null) continue;
            result.add(node.val);
            nodeStack.push(node.right);
            nodeStack.push(node.left);
        }
        return result;
    }

}
//迭代中序遍历
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        Stack<TreeNode> nodeStack = new Stack<>();
        TreeNode node = root;
        while(node != null || !nodeStack.empty()){
            while(node != null) {
                nodeStack.push(node);
                node = node.left;
            }
            node = nodeStack.pop();
            if(node == null) continue;
            result.add(node.val);
            node = node.right;
            
        }
        return result;
    }
}
//后续迭代遍历
class Solution {
   public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        if (root == null){
            return result;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.empty()){
            TreeNode node = stack.pop();
            result.add(node.val);
            if (node.left != null){
                stack.push(node.left);
            }
            if (node.right != null){
                stack.push(node.right);
            }
        }
        Collections.reverse(result);
        return result;
    }
}

先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了,如下图:请添加图片描述





二叉树的层序遍历

102. 二叉树的层序遍历

//通过队列进行迭代遍历
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        if(root != null) que.add(root);
        TreeNode temp;
        while(!que.isEmpty()){
            List<Integer> itemList = new ArrayList<Integer>();
            int len = que.size();
            while(len-- > 0){    
                temp = que.poll();
                itemList.add(temp.val);
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
            result.add(itemList);
        }
        return result;
    }
}
class Solution {
    public List<List<Integer>> resList = new ArrayList<List<Integer>>();

    public List<List<Integer>> levelOrder(TreeNode root) {

        checkFun01(root,0);

        return resList;
    }

    //DFS--递归方式
    public void checkFun01(TreeNode node, Integer deep) {
        if (node == null) return;

        if (resList.size() == deep) {
            //当层级增加时,list的Item也增加,利用list的索引值进行层级界定
            List<Integer> item = new ArrayList<Integer>();
            resList.add(item);
        }
        resList.get(deep).add(node.val);

        checkFun01(node.left, deep + 1);
        checkFun01(node.right, deep + 1);
    }
}






107. 二叉树的层序遍历 II

//102的基础上反转一下就可以了。
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        if(root != null) que.add(root);
        TreeNode temp;
        while(!que.isEmpty()){
            List<Integer> itemList = new ArrayList<Integer>();
            int len = que.size();
            while(len-- > 0){    
                temp = que.poll();
                itemList.add(temp.val);
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
            result.add(itemList);
        }
        List<List<Integer>> list = new ArrayList<>();
        for (int i = result.size() - 1; i >= 0; i-- ) {
            list.add(result.get(i));
        }
        return list;
    }
}






199.二叉树的右视图

//层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        List<Integer> result = new ArrayList<Integer>();
        if(root != null) que.add(root);
        TreeNode temp;
        while(!que.isEmpty()){
            int len = que.size();
            for (int i = 0; i < len; i++){    
                temp = que.poll();
                if(i == len -1 ) result.add(temp.val);
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
        }
        return result;
    }
}






637.二叉树的层平均值

//思路同上面那个类似
class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        List<Double> result = new ArrayList<Double>();
        if(root != null) que.add(root);
        TreeNode temp;
        while(!que.isEmpty()){
            int len = que.size();
            double sum = 0;
            for (int i = 0; i < len; i++){    
                temp = que.poll();
                sum += temp.val;
                if(i == len -1 ) result.add(sum/len);
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
        }
        return result;
    }
}






429.N叉树的层序遍历

//
class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        Queue<Node> que = new LinkedList<Node>();
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if(root != null) que.add(root);
        Node temp;
        while(!que.isEmpty()){
            List<Integer> itemList = new ArrayList<Integer>();
            int len = que.size();
            for (int i = 0; i < len; i++){    
                temp = que.poll();
                itemList.add(temp.val);
                //将指定集合中的所有元素按指定集合的迭代器(可选操作)返回的顺序追加到此列表的末尾。
                que.addAll(temp.children);
            }
            result.add(itemList);
        }
        return result; 
    }
}






515.在每个树行中找最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        List<Integer> result = new ArrayList<Integer>();
        if(root != null) que.add(root);
        TreeNode temp;
        while(!que.isEmpty()){
            int len = que.size();
            int num = Integer.MIN_VALUE;
            for (int i = 0; i < len; i++){    
                temp = que.poll();
                num = (num > temp.val)?num : temp.val;
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
            result.add(num);
        }
        return result;
    }
}






116.填充每个节点的下一个右侧节点指针

117.填充每个节点的下一个右侧节点指针II

class Solution {
    public Node connect(Node root) {
        Queue<Node> que = new LinkedList<Node>();
        if(root != null) que.add(root);
        Node temp1,temp2;
        while(!que.isEmpty()){
            int len = que.size();
            while(len-- > 0){    
                temp1 = que.poll();
                temp2 = que.peek();
                if(len >= 1){
                    temp1.next = temp2;
                }
                if(temp1.left != null) que.add(temp1.left);
                if(temp1.right != null)  que.add(temp1.right);
            }
        }
        return root;  
    }
}






104.二叉树的最大深度

//迭代
class Solution {
    public int maxDepth(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        if(root != null) que.add(root);
        int deep = 0;
        TreeNode temp;
        while(!que.isEmpty()){
            List<Integer> itemList = new ArrayList<Integer>();
            int len = que.size();
            if(len > 0) deep++;
            while(len-- > 0){    
                temp = que.poll();
                itemList.add(temp.val);
                if(temp.left != null) que.add(temp.left);
                if(temp.right != null)  que.add(temp.right);
            }
        }
        return deep;
    }
}
//递归
class Solution {
    int deep = 0; 
   public int maxDepth(TreeNode root){
        if(root == null)
            return 0;
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        deep = Math.max(left, right)+1;
        return deep;
    }
}






111. 二叉树的最小深度

//递归方法
class Solution {
    int deep = 0;
    public int minDepth(TreeNode root) {
        if(root == null) return 0;

        int left =  minDepth(root.left);
        int right = minDepth(root.right);
        if(root.left == null) deep = right + 1;
        else if(root.right == null) deep = left + 1;
        else deep = Math.min(left, right)+1;
        return deep;
    }
}
//迭代法
class Solution {
    public int minDepth(TreeNode root) {
        int deep = 0;
        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()){
            int len = queue.size();
            deep++;
            while(len-- > 0 ){
                TreeNode temp = queue.poll();
                 
                if( temp.left == null && temp.right == null ) return deep;
                if(temp.left != null) queue.add(temp.left);
                if(temp.right != null) queue.add(temp.right);
            }
        }
        return deep;
    }
}






226. 翻转二叉树

//递归
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root != null) {
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            invertTree(root.left);
            invertTree(root.right);
        }
        return root;
    }
}






101. 对称二叉树

//迭代的方法,使用两个队列,左右队列分别装根的左右树,并且右队列是从右节点往左节点装数据。
class Solution {
    public boolean isSymmetric(TreeNode root) {
        Queue<TreeNode> leftQue = new LinkedList<TreeNode>();
        Queue<TreeNode> rightQue = new LinkedList<TreeNode>();
        if(root.left == null && root.right == null) return true;
        //System.out.println(root.left.val);
        leftQue.add(root.left);
        rightQue.add(root.right);
        TreeNode leftTemp,rightTemp;
        while(!leftQue.isEmpty() && !rightQue.isEmpty()){
            int len1 = leftQue.size();
            int len2 = rightQue.size();
            if(len1 != len2) return false;
            while(len1-- > 0){
                leftTemp = leftQue.poll();
                rightTemp = rightQue.poll();
                if(leftTemp == null && rightTemp == null) continue;
                else if(leftTemp == null || rightTemp == null ) return false;
                else if(leftTemp.val == rightTemp.val) {
                    leftQue.add(leftTemp.left);
                    leftQue.add(leftTemp.right);
                    rightQue.add(rightTemp.right);
                    rightQue.add(rightTemp.left);
                }
                else return false;
            }
        }
        return true;
    }
}
//递归
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root.left == null && root.right == null) return true;
        return match(root.left, root.right);
    }
    public boolean match(TreeNode left,TreeNode right){
        if(left == null && right == null) return true;
        if(left == null || right == null) return false;
        if(left.val == right.val){
            boolean a = match(left.left,right.right);
            boolean b = match(left.right,right.left);
            if(a == true && b == true) return true;
        }
        return false;
    }
}






222.完全二叉树的节点个数

//迭代
class Solution {
    public int countNodes(TreeNode root) {
        int result = 0;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()){
            int len = queue.size();
            result += len;
            while(len-- > 0 ){
                TreeNode temp = queue.poll();
                if(temp.left != null) queue.add(temp.left);
                if(temp.right != null) queue.add(temp.right);
            }
        }
        return result;
    }
}
/递归
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}






110.平衡二叉树

//疯狂的递归。
class Solution {
    boolean a = true;
    boolean b = true;
    public int high(TreeNode root){
        if(root == null) return 0;
        int left = high(root.left);
        int right = high(root.right);
        if(left > right){
            if(Math.abs(left - right) > 1)
                a = false;
        }
        else{
            if(Math.abs(left - right) > 1)
                b = false;
        }
        
        return Math.max(left,right) + 1;
    }
    public boolean isBalanced(TreeNode root) {
        if(root == null) return true;
        high(root);
        if(a == true && b == true)
            return true;
        return false;

    }
}






257. 二叉树的所有路径

//递归,使用前序遍历的递归方式(因为寻找的路径是从根节点到叶子节点,首先要遍历根结点)。
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();
        List<Integer> paths = new ArrayList<>();//存放节点值
        traversal(root,paths,res);
        return res;
    }
    private void traversal(TreeNode root, List<Integer> paths, List<String> res){
        paths.add(root.val);//中
        //找到叶节点,输出。
        if(root.left == null && root.right == null){
            StringBuilder sb = new StringBuilder();
            for(int i = 0;i < paths.size() - 1;i++){
                sb.append(paths.get(i)).append("->");
            }
            sb.append(paths.get(paths.size()-1));//添加最后一个节点值
            res.add(sb.toString());
            return ;
        }
        if(root.left != null) {
            traversal(root.left,paths,res);
            paths.remove(paths.size() - 1);//回溯(说白了就是给前一个加进去的节点去掉)
        }
        if(root.right !=null) {
            traversal(root.right,paths,res);
            paths.remove(paths.size() - 1);
        }
        
    }
}
class Solution {
    /**
     * 迭代法
     */
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> result = new ArrayList<>();
        if (root == null)
            return result;
        Stack<Object> stack = new Stack<>();
        // 节点和路径同时入栈
        stack.push(root);
        stack.push(root.val + "");
        while (!stack.isEmpty()) {
            // 节点和路径同时出栈
            String path = (String) stack.pop();
            TreeNode node = (TreeNode) stack.pop();
            // 若找到叶子节点
            if (node.left == null && node.right == null) {
                result.add(path);
            }
            //右子节点不为空
            if (node.right != null) {
                stack.push(node.right);
                stack.push(path + "->" + node.right.val);
            }
            //左子节点不为空
            if (node.left != null) {
                stack.push(node.left);
                stack.push(path + "->" + node.left.val);
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值