数组链表算法思路一

2020-02-01  本文已影响0人  你值得拥有更好的12138

解题方法:

思维

首先请放弃你那种暴力法,即动不动就上双重循环的思维方式。
然后更多的使用切分和线性的方式去做数组或者链表的题,在动态规划中更是这样。

例题一

解题方法:使用快慢指针+Map进行辅助统计计算

总结一句话:连续不重复字串最长

题目内容
LeetCode 第 03 题:给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

示例 1
输入:"abcabcbb"
输出:3
解释:因为无重复字符的最长子串是"abc",其长度为3。

解题思路:

使用快慢指针(slow,fast)的方式,当fast前进一步就向Map中进行put一个元素,当遇到Map中包含这个元素时,就进行删除。

怎么删除呢?
使用Map获取相同字符的位置然后加一,并且更新slow指针

怎么计算长度呢?
快慢指针位置相减加一

下面的解题方法有两种:
1.使用指针一个一个删除这种方式显然是很多次是多余
2.使用Map进行跳跃,那就可以省去了很多次的删除过程

public class ContinuousNonRepetitionString {
    
    public static void main(String[] args) {
        String[] data = {"d","e","a","d","c","a","q"};
        System.out.println(new ContinuousNonRepetitionString().length(data));
        System.out.println(new ContinuousNonRepetitionString().lengthStep(data));
    }

    /**
     * 使用Map快速跳转慢指针的方法
     * @param nums
     * @return
     */
    private int length(String[] nums){
        int i = 0;
        int j = 0;
        Map<String,Integer> temp = new HashMap<>();
        int max = 0;
        for(;j<nums.length;j++){
            if(temp.containsKey(nums[j])){
                i = temp.get(nums[j])+1;
            }
            temp.put(nums[j],j);
            max=Math.max(max,j-i+1);
        }
        return max;
    }


    /**
     * 使用循环删除的方式,更新慢指针
     * @param nums
     * @return
     */
    private int lengthStep(String[] nums){
        int i = 0;
        int j = 0;
        Set<String> temp = new HashSet<>();
        int max = 0;
        for(;j<nums.length;j++){
            while (temp.contains(nums[j])){
                temp.remove(nums[i]);
                i++;
            }
            temp.add(nums[j]);
            max=Math.max(max,j-i+1);
        }
        return max;
    }
}

例题二

解题方法:使用快排的思想进行查找,并不是把全部的元素排序

总结一句话: 找中位数

题目:
LeetCode 第 04 题:给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m+n))。
你可以假设 nums1 和 nums2 不会同时为空。

示例1
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例2
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5

解题思路

换一种思路想:
首先将两个数组合并

然后找第k大的元素,当我们使用快速排序的时候,每排序一轮后,中间的那个元素就就是第k大元素,所以我们可以通过比较k值得大小决定向左还是向右继续比较,另一边就不需要管了。这样就降低的时间复杂度

此题有两种情况:
1.数组是奇数,中位数为 第k大的元素 k=nums.length/2 ,排序后的坐标为k-1
2.数组是偶数,中位数为 第k大和第k+1大的平均值

public class MedianQuickMethod {
    public static void main(String[] args) {
            int[] nums = {1,3,5,7,9,11,13,15};//1,3,5,7,9,15,13,11
            //15,3,5,7,9,1,13,11
            //15,13,11,7,9,1,3,5
            System.out.println(new MedianQuickMethod().findMedian(nums));
    }

    private double findMedian(int[] nums){
        int k = nums.length/2;
        if((nums.length)%2 == 0){
            double k1= quick(nums,0,nums.length-1,k);
            double k2= quick(nums,0,nums.length-1,k+1);
            return (k1+k2)/2f;

        }else {
          return   quick(nums,0,nums.length-1,k+1);
        }
    }

    private double quick(int[] nums,int low,int he,int k){
       int pivot = (int) (Math.random()*(he-low+1)+low);
//       int pivot = low;
       swap(nums,pivot,he);
       int finishPos = low;
        System.out.println("p:"+nums[he]);
       for(int i=low;i<nums.length;i++){
          if(nums[i]>nums[he]){
              swap(nums,i,finishPos);
              finishPos++;
          }
       }
       swap(nums,he,finishPos);
        System.out.println(Arrays.toString(nums));

       //第几个
       int tempk = finishPos-low+1;
        System.out.println("第k大:"+tempk + "要求:" + k);
       if(tempk==k)
           return nums[finishPos];
       else if(tempk<k)
           return quick(nums,finishPos+1,he,k-tempk);
       else
           return quick(nums,low,finishPos-1,k);
    }


    private void swap(int[] nums,int i,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

上一篇 下一篇

猜你喜欢

热点阅读