hot100刷题:数组——11、15

11. 盛最多水的容器

思路:
首先根据实例1,能够判断出水的容积就是(两块板中的短板长度)*(两块板之间的距离),用数学公式表示就是:S(i,j) = min(h[ i ] , h[ j ]) × (j − i),这里用到的是双指针的思想来实现。首先两个指针都指向最两端的两块木板,然后不断让两块木板中较短的那块向内移动,移动过程中不断计算新的面积的大小,如果比前一次的大就进行记录。
证明:如果使用枚举法,得到的面积的总数是(假如有n块木板):n+(n-1)+(n-2)+…+1种情况,然后在这么多种情况中选择最大值。现在假设i,j中,i是较短的那块木板,那么i向内移动,面积变成了S(i+1,j),也就是将枚举中的(i,j-1),(i,j-2),……,(i,i+1)这些情况跳过了,而这些情况中,根据公式S(i,j) = min(h[ i ] , h[ j ]) × (j − i),两块木板间的距离变短,而且min(h[ i ] , h[ j ])只有不变或者变小的情况,所以跳过的所有情况都是小于S(i,j),因此分析正确。
hot100刷题:数组——11、15_第1张图片
代码:

class Solution {
    public int maxArea(int[] height) {
        int i=0;
        int j=height.length-1;
        int res=0,temp=0;
        while(i<j){
            if(height[i]<=height[j]){
                temp=height[i]*(j-i);
                i++;
            }else{
                temp=height[j]*(j-i);
                j--;
            }
            if(res<temp) res=temp;
        }
        return res;
    }
}

15. 三数之和

思路:这道题依然使用双指针构造,首先将数组进行排序(因为给粗的实例中,集合中的数组是按从小到大的顺序排列)。然后将k固定,i,j作为两个指针,由于i,j,k三者不能相等,所以i是从k+1处开始移动,j是从最后一个位置开始移动。每次分为三种情况:
首先可以先进行判断,如果k处数组的值已经大于0,说明三者的和不可能等于0,直接结束
1、如果三个数相加的和大于0,让i后移一位(且不能和原位置处的元素相同)
2、如果三个数相加的和小于0,让j前移一位(且不能和原位置处的元素相同)
3、如果三个数相加的和等于0,让i后移一位且j前移一位(且不能和原位置处的元素相同),并将数组存储到集合中

自己写的超级复杂的代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int k=0,i=0,j=nums.length-1;
        int tempk=0,tempi=0,tempj=0;//分别用于记录当前位置,以便在指针移动时能移动到不重复的元素
        List<List<Integer>> res=new LinkedList<>();
        // while(k
        while(k<j){
            i=k+1;tempk=k;j=nums.length-1;
            // while(i
            // tempk=i;
            //上面的写法本意是让下次k的位置能够移动到与现有位置元素不同的位置,但是这种写法
            //会使得i指针所指元素也和现有的k所在的元素不能重复,但其实i,k只是有i!=k的条件
            //没有nums[k]!=nums[i]的条件,会漏情况!
            while(i<j){
                if(nums[k]+nums[i]+nums[j]<0){
                    tempi=i;
                    i++;//这句其实可以省略,包括下面的j--
                    while(i<j&&nums[i]==nums[tempi]) i++;
                }else if(nums[k]+nums[i]+nums[j]>0){
                    tempj=j;
                    j--;
                    while(i<j&&nums[j]==nums[tempj]) j--;
                }else{
                    List tList=new LinkedList<Integer>();
                    tList.add(nums[k]);
                    tList.add(nums[i]);
                    tList.add(nums[j]);
                    res.add(tList);
                    tempi=i;
                    i++;
                    while(i<j&&nums[i]==nums[tempi]) i++;
                    tempj=j;
                    j--;
                    while(i<j&&nums[j]==nums[tempj]) j--;
                }
            }
             while(k<j&&nums[k]==nums[tempk])k++;
        // k=tempk;
        }
        return res;
    }
}

答案代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<>();
        for(int k = 0; k < nums.length - 2; k++){
            if(nums[k] > 0) break;
            if(k > 0 && nums[k] == nums[k - 1]) continue;
            int i = k + 1, j = nums.length - 1;
            while(i < j){
                int sum = nums[k] + nums[i] + nums[j];
                if(sum < 0){
                    while(i < j && nums[i] == nums[++i]);
                } else if (sum > 0) {
                    while(i < j && nums[j] == nums[--j]);
                } else {
                    res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
                    while(i < j && nums[i] == nums[++i]);
                    while(i < j && nums[j] == nums[--j]);
                }
            }
        }
        return res;
    }
}

你可能感兴趣的:(leetcode,算法,数据结构,leetcode)