Skip to content

Latest commit

 

History

History
428 lines (329 loc) · 12.2 KB

双指针.md

File metadata and controls

428 lines (329 loc) · 12.2 KB

双指针思想:

思路:题目太简单,首尾两指针

错误:

​ 1、题目要求输出的下标从1开始而不是从0

​ 2、Java语言问题 数组初始化、数组长度函数

代码:

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int i = 0;
        int j = numbers.length-1;
        while(i<j){
            if(numbers[i] + numbers[j] < target) i++;
            else if(numbers[i] + numbers[j] > target)  {
                j--;
            }
            else{
                break;
            }
        }
        int[] res = new int[2];
        res[0] = i+1;
        res[1] = j+1;
        return res;

    }
}

题目:给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a2 + b2 = c

思路:题目稍有变化,不能从最后开始,右指针要从开方开始

错误:

​ 1、Java语言问题 类型强制转换、开方函数、求幂函数

​ 2、性能问题 右指针要从开方开始

​ 3、题目初始条件 if (target < 0) return false;

class Solution {
    public boolean judgeSquareSum(int c) {
        if (target < 0) return false;
        int i = 0;
        int j = (int)Math.sqrt(c);
        boolean res = false; 
        while(i <= j){
            if(i * i + j * j < c) i++;
            else if (i * i + j * j > c) j--;
            else{
                res = true;
                break;
            }
        }
        return res;
    }
}

思路:双指针,如果都是元音就交换,并且指针同时移动,如果左不是元音,移动左指针,其他情况都移动右指针

错误:

​ 1、交换之后没有移动指针,导致死循环

​ 2、Java语法问题: 数组初始化、char数组和string的互换、string中的元素交换、定位元素、string长度获取。

代码:

class Solution {
    public boolean isYuanyin(char a){
        if(a == 'a' || a =='o'|| a =='e' || a =='i'|| a =='u'||a == 'A' || a =='O'|| a =='E' || a =='I'|| a =='U') return true;
        else return false;
    }
    public String reverseVowels(String s) {
        int i = 0, j = s.length() - 1;
        char[] array = s.toCharArray();
        while(i < j){
            char left = array[i];
            char right = array[j];
            if(isYuanyin(left) && isYuanyin(right)){
                char temp = left;
                array[i] = right;
                array[j] = temp;
                i++;
                j--;
            }
            else if(!isYuanyin(left) && isYuanyin(right)){
                i++;
            }
            else j--;
        }
        String res  = String.valueOf(array); 
        //String res = new String(array); 
        return res;
    }
    
}

给定一个非空字符串 s最多删除一个字符。判断是否能成为回文字符串。

输入: s = "aba"
输出: true

看了答案

思路:双指针,左右两边都可以去掉字符,如果出现了不同,去掉右边的或者去掉左边的字符,然后判断剩下的是否是回文

错误:

​ 思路问题,没有考虑左右的问题,我的想法是如果左右两个不同,那么就比较两种情况:i+1和j或者i和j-1,然后用num来标记去掉了几个,如果num>=2 的话,那么就说明不回文,这个思路存在两个问题

​ (1)先进行第一种比较,后比较第二种,这样左右就是不公平的

​ (2)如果不相同的话,else中无法继续进行下去

​ 后来又想到了递归的思路,但是递归无法找到出口

class Solution {
    public boolean validPalindrome(String s) {
        int i = 0, j = s.length() - 1;
        int num = 0;
        while(i < j){
            char left = s.charAt(i);
            char right = s.charAt(j);
            if (left == right){
                i++;
                j--;
            }
            else{
                return isValid(s, i+1, j)||isValid(s, i, j-1);
            }
        }
        return true;
    }
    public boolean isValid(String s, int i, int j){
        while (i<j){
            if (s.charAt(i) == s.charAt(j)){
                i++;
                j--;
            }
            else return false;
        }
        return true;
    }
}

思路和错误:

我的思路:

​ 另外建立一个数组存储两者的比较结果 ,并且从头开始进行插入

例题思路:

​ 从后开始比较,并直接存入,因为题目定义nums1存在这么多空间

思路中要有前后的思想

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i=m-1, j=n-1, k=m+n-1;
        while(i>=0 || j>=0){
            if(i<0){
                nums1[k--] = nums2[j--];           
            }
            else if(j<0){
                break;
            }
            else if(nums1[i]>nums2[j]){
                nums1[k--] = nums1[i--];     
            }
            else{
                nums1[k--] = nums2[j--];
            }
        }
    }
}

2021/4/1

思路:快慢指针

关键:

1、只要指针非空,必有next,考虑不能太复杂

2、static下怎么使用非静态方法:实例化!!!!!!

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null){
            return false;
        }
        ListNode L1 = head;
        ListNode L2 = head.next;
        while(L1 != null && L2 != null && L2.next != null){
            if(L1 == L2) return true;
            L1 = L1.next;
            L2 = L2.next.next; 
        }
        return false;

    }
}

`

2021/4/1

给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串

思路:双指针

思路错误:

1、没有判断now是不是s 的子串(题目理解不透彻)

2、不知道什么是字典顺序 compareTo()

3、如果没有匹配的,忘记返回空字符串 -->""而不是null(边界判断)

技术缺陷:

1、List实例化和初始化

2、字典顺序比较方法

3、字符串长度获取和List长度获取不同

class Solution {
        public String findLongestWord(String s, List<String> dictionary) {
            int maxlen = 0, maxorder = -1;
            for (int k = 0; k < dictionary.size() ; k++) {
                String now = dictionary.get(k);
                int len = 0, i = 0, j = 0;
                while (j < now.length() && i < s.length()){
                    if (s.charAt(i) == now.charAt(j)){
                        i++;
                        j++;
                        len++;
                    }
                    else i++;
                }
                if (j != now.length()){
                    continue;
                }
                if (len > maxlen) {
                    maxlen = len;
                    maxorder = k;
                }
                else if (len == maxlen){
                    maxorder = now.compareTo(dictionary.get(maxorder))>0?maxorder:k;
            }
            }
            if(maxorder == -1) return "";
            else return dictionary.get(maxorder);
        }
}

快速排序

思路:找到基准数(开始位置的数),前后双指针,分别找到比基准大和比基准小的数的位置,将两数进行交换,递归进行排序。最后,将前指针的数放到基准数位置(开始位置),然后将基准数放到前指针这里。

public void sortQ(int[] nums, int start, int end){
        if (start > end) return;
        int temp = nums[start], i = start, j = end;
        while( i < j && i >= 0 && j < nums.length){
            while (nums[j] >= temp && i<j){
                j--;
            }//先让j往前走,因为最后要交换i和start
            while (nums[i] <= temp && i<j){
                i++;
            }
            if (i < j) {
                int t = nums[i];
                nums[i] = nums[j];
                nums[j] = t;
            }//当找到左边比temp大,右边比temp小的数的时候,两者交换
        }

        nums[start] = nums[i];//将i交换到开始,因为nums[i]一定小于temp
        nums[i] = temp; //然后将temp放到i这里

        sortQ(nums, start, i-1);
        sortQ(nums, i+1, end);
    }

思路:桶排序

​ 1、使用map键值对存储数据, 注意map的一些操作

​ 2、空间换时间,使用下标来表示次数,并在每个位置存储一个List,每个List存储所有出现这么多次的数

​ 3、从后面开始遍历到第k个数,将所有满足要求的数存储到一个数组中

 public static int[] getK(int[] nums, int k){
        Map<Integer, Integer> m = new HashMap<>();
//      map字典
        for (int num : nums){
            m.put(num, m.getOrDefault(num,0) + 1);
//			使用map形式存储各个数字的出现次数,如果键在字典中没有出现,那么
//          设定其Default为0,如果出现,则获取该键的值(数字的出现次数)+1,
//          并重新赋值   
        }
        List<Integer>[] bucket = new ArrayList[nums.length+1];
        //注意这个定义,每个bucket中存的是一个list
        for (int key : m.keySet()){
            int val = m.get(key);
            if (bucket[val] == null){
                bucket[val] = new ArrayList<>();
            }
            bucket[val].add(key);
        }
    	//bucket就是桶,每个桶的下标代表出现的次数	
        List<Integer> resList = new ArrayList<>();
    	//最终结果List
        for (int i = bucket.length - 1; i > 0 ; i--) {
             if (k == 0){
                break;
            }
            if (bucket[i] == null){
                continue;
                //如果桶中该值对应元素为空,就继续
            }
            for (int n : bucket[i]){
                resList.add(n);
                //如果不为空的话,就获取该次数下的元素
                k--;
            }
        }
        int[] result = new int[resList.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = resList.get(i);
        }
     	//将list转化为需啊哟的数组格式返回
        return result;
    }

快速排序练习,注意一定要让j先移动

  if (i > j){
            return;
        }
        int start = i, end = j;
        int mid = nums[i];
        while (i < j){
        while (nums[j] >= mid && i<j){
                        j --;
                    }

            while(nums[i] <= mid && i<j){
                i ++;
            }
            
            if (i < j){
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        nums[start] = nums[i];
        nums[i] =mid;
        Qsort(nums, start, i - 1);
        Qsort(nums, i + 1, end);

    }