Leetcode刷题之Array篇

1. Two Sum

Code it now! https://leetcode.com/problems/two-sum/

难度:easy


问题描述:

一个整数数组,找出某两个数加和等于某一个特定的数(target)。

要求函数twoSum返回符合要求的两数在数组中所处的位置,index1和index2(index1必须小于index2)。请注意,你所编写的函数返回值应该是下标加1.(本题只需要考虑仅有唯一解的情况)。

解题思路:

  暴力算法:时间复杂度O(n^2),空间复杂度O(1)。

     本题前提条件(仅有唯一解,且index1小于index2),故排除同一元素使用两次的情况,只需遍历数组中每个元素i,然后在剩余元素中查找是否存在j使得i+j=target,因为双重遍历数组,因此时间复杂度为n^2代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int index1 = 0;
        int index2 = 0;
        int[] res = new int[2];
        //双重循环遍历每个元素是否满足要求
        for(int i=0;i

   
  哈希表法:时间复杂度O(n),空间复杂度O(n)。

    通过HashMap把元素值和索引存储起来,因为HashMap检索值的时间复杂度为O(1),故实现了空间换时间,代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int index1 = 0;
        int index2 = 0;
        int[] res = new int[2];
        Map map = new HashMap();
        
        for(int i=0;i

167.Two Sum II - Input array is sorted

Code it now! https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/

难度:easy


问题描述:

给定有序数组和target找到两数之和为target的两数下标。

只有唯一解,同一元素只能使用一次。

解题思路:

  遍历算法:时间复杂度O(n),空间复杂度O(1)。

 本题用到两指针法,因为数组已排好序,因此只需要两指针一前一后定位到两元素之和为target的两元素,并记录下元素下标即可求解。代码如下:

 

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int start  = 0;
        int end    = numbers.length-1;
        int index1 = 0;
        int index2 = 0;
        while(true)
        {
            //双指针寻值操作
            if(numbers[start]+numbers[end]==target){
                index1 = start+1;
                index2 = end+1;
                break;
            }else if(numbers[start]+numbers[end]>target){
                end--;
            }else{
                start++;
            }
        }
        int[] res = {index1,index2};
        return res;
    }
}




15. 3Sum

Code it now! https://leetcode.com/problems/3sum/

难度:Medium


问题描述:

给定一个数组,找出其中所有不同的三数和等于0的组合。

要求找出所有不重复组合。

解题思路:

  暴力算法:三层for循环,时间复杂度O(n^3),还需要删除重复答案显然不是合适解法。

  优化算法:类比Two-Sum问题,我们想到能否在这三个数当中固定一个数i,剩下两位数之和为i的相反数。

  我们可以先对数组进行排序,固定一个数i,并在剩下数组中求两数之和为-i,最后用两个指针分别从前后两端向中间搜索即可(此题需要考虑两处结果集重复问题)。时间复杂度为O(n^2),代码如下:

class Solution {
    
    public List> threeSum(int[] nums) {
        List> res = new ArrayList>();
        if(nums.length<3)
            return res;

        Arrays.sort(nums);
        for(int i=0;i0&&nums[i]==nums[i-1])
                continue;
            findTwosum(nums,i+1,nums.length-1,nums[i],res);
        }  
        return res;
      
    }
    public static void findTwosum(int[] nums,int start,int end,int value,List> res){
        while(start temp = new ArrayList();
                temp.add(nums[start]);
                temp.add(nums[end]);
                temp.add(value);
                res.add(temp);
                //题目要求结果不可重复,此步骤为去重操作。
                while(start0){
                end--;
            }else{
                start++;
            }
        }
    }
}

 元素已排好序,通过对前后相邻元素判断并进行跳过的操作,能够有效避免解集重复的问题。注意看注释两个去重操作。

 

 此3sum的去重操作也可采用Set集合来实现,从而减少了两层逻辑判断去除重复,代码如下,亦是4sum解题框架。

 

class Solution {
    public List> threeSum(int[] nums) {
        List> list = new ArrayList>();
        Set> res = new HashSet>();
        if(nums.length<3)
            return list;
        
        Arrays.sort(nums);
        //首先固定数组中的一个元素。
        for(int i=0;i temp = new ArrayList();
                    temp.add(nums[i]);
                    temp.add(nums[left]);
                    temp.add(nums[right]);
                    res.add(temp);
                    left++;
                    right--;
                }
                else if(sum<0)
                    left++;
                else
                    right--;
            } 
        }
        //将Set中的解集,转换成List中去。
        for(List temp:res){
            list.add(temp);
        }
        return list;
    }
}


 


18. 4Sum

Code it now! https://leetcode.com/problems/4sum/

难度:Medium


问题描述:

给定一个整数数组,找出所有不同的四数之和等于0的组合。

要求找出所有不重复组合。

解题思路:

  前面的2sum用到的是固定其中一个值,然后在剩余数组中寻找另一个值;3sum用到的是固定其中一个值,然后在剩余已排好序的数组中寻找另外两个值是否能够满足条件,时间复杂度是O(n^2);其实4sum的解题思路也就是相比于3sum多一层for循环,固定前两个值,然后在剩下排好序的数组中寻找另外两个值,时间复杂度是O(n^3)。

  此题4sum有用到HashSet来避免解集重复问题,从而降低了算法的思维难度。算法如下:

class Solution {
    public List> fourSum(int[] nums, int target) {
        List> List = new ArrayList>();
        Set> res = new HashSet>();
        if(nums.length<4)
            return List;
        
        Arrays.sort(nums);
        //两层for循环可先选出数组中两个不同元素,然后在剩下排好序的数组中选另外两个不同元素。
        for(int i=0;i temp = new ArrayList();
                        temp.add(nums[i]);
                        temp.add(nums[j]);
                        temp.add(nums[left]);
                        temp.add(nums[right]);
                        res.add(temp);
                        ++left; --right;
                    } 
                    else if (sum < target) 
                        ++left;
                    else 
                        --right;
                }
                }
            }
        //将存在Set中的解集转成存在List中,并return。
        for(List temp:res){
            List.add(temp);
        }
        return List;
        }
}
  前面所讲到的k-sum问题,都是一个可用一个框架来搞定,也就是固定某值,找剩余值法。




26.Remove Duplicates from Sorted Array

Code it now! https://leetcode.com/problems/remove-duplicates-from-sorted-array/

难度:easy


问题描述:

给定一个有序数组,删除重复内容,使每个元素只出现一次,并返回新的长度。

数组是有序的,只能使用O(1)的额外空间,且不重复元素有序排列在数组中。

解题思路:

  哈希表算法:时间复杂度O(n),空间复杂度O(n),不符合题意

  双指针法:时间复杂度O(n),空间复杂度O(1)。

 本题当中数组是有序的,采用两个指针索引计数操作。代码如下:

 

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums.length == 0) return 0;
        int i = 0;
        //双指针循环遍历数组。
        for (int j = 1; j < nums.length; j++) {
            if (nums[j] != nums[i]) {
                i++;
                nums[i] = nums[j];
            }
        }
        return i + 1;
    }
}



27.Remove Element

Code it now! https://leetcode.com/problems/remove-element/

难度:easy


问题描述:

给定一个有序数组和一个target,删除数组中的target并返回新长度。

只能使用O(1)的额外空间,且在新长度数组中,排列好非target元素。

解题思路:

  双指针法:时间复杂度O(n),空间复杂度O(1)。

 本题采用双指针,一个指针保证了新长度数组的元素排列好非target元素(可在原数组中进行操作,获得新数组,以该指针作为标记),另一指针迅速遍历整个数组。代码如下:

 

class Solution {
    public int removeElement(int[] nums, int val) {
        if(nums.length==0) return 0;
        //双指针操作,一个用于替换原数组的值,一个用于不断向后遍历整个数组。
        int i=0;
        for(int j=0;j



34.Search for a Range

Code it now! https://leetcode.com/problems/search-for-a-range/

难度:medium


问题描述:

给定按升序排序的整数数组,找到给定目标值的开始和结束位置。

算法时间复杂度为O(log n)。

解题思路:

  二分查找法:时间复杂度O(log n),空间复杂度O(1)。

 本题使用了二分搜索的思想,一般遇到O(log n)时间复杂度的算法大多有涉及到二分思想。因为数组是有序的,因此在二分搜索到目标值之后,分别向前向后找到目标值的开始和结束索引即为所求。代码如下:

 

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res = {-1,-1};
        int start = 0;
        int end = nums.length-1;
        int i=0;
        int j=0;
        //二分搜索框架。
        while(start<=end){
            int mid = (start+end)/2;
            if(nums[mid]==target)
            {
                //从目标值索引位置往前找。
                for(i=mid-1;i>=start;i--){
                    if(nums[i]!=target)
                        break;
                }
                res[0]=i+1;
                //从目标值索引位置往后找。
                for(j=mid+1;j<=end;j++){
                    if(nums[j]!=target)
                        break;
                }  
                res[1]=j-1;
                return res;   
            }
            else if(nums[mid]>target){
                end = mid-1;
            }
            else{
                start = mid+1;
            }
        }
        return res;
    }
}



35.Search Insert Position

Code it now! https://leetcode.com/problems/search-insert-position/

难度:easy


问题描述:

给定有序数组和target,找到target则返回索引,否则返回按顺序插入的位置。

数组无重复元素。

解题思路:

  二分查找法:时间复杂度O(log n),空间复杂度O(1)。

 本题使用了二分搜索的思想,在二分搜索框架代码中进行一定操作即可。代码如下:

 
class Solution {
    public int searchInsert(int[] nums, int target) {
        int start = 0;
        int end   = nums.length-1;
        int mid   = 0;
        while(start<=end)
        {
            mid = (start+end)/2;
            if(nums[mid]==target){
                return mid;
            }
            else if(nums[mid]>target)
                end   = mid-1;
            else
                start = mid+1;
        }
        //二分搜索没找到target,则最后索引为所求需要插入的位置。
        return start;
    }
}



55.Jump Game

Code it now! https://leetcode.com/problems/jump-game/

难度:medium


问题描述:

给定一个非负整数数组,最初定位在数组第一个索引处,数组中每个元素值表示在当前位置所能跳跃的最大长度,确定能否跳到最后一个位置。

解题思路:

  贪心算法:时间复杂度O(n),空间复杂度O(1)。

 本题使用了贪心策略,用farthest记录当前所在位置所能跳跃的最远距离,如果当前所能跳跃的最远距离小于当前的索引位置则为不可达返回false,如果当前所能跳跃的最远距离大于等于数组大小则能够跳到最远位置返回true。代码如下:

class Solution {
    public boolean canJump(int[] nums) {
        int farthest = 0;
        boolean res  = false;
        for(int i=0;i=nums.length-1){
                res = true;
                break;
            }
        }
        return res;   
    }
}

 更通俗版贪心算法如下:

 

class Solution {
    public boolean canJump(int[] nums) {
        //贪心算法
        int len = nums.length;
        int max = -1;
        int temp = 0;
        // 保存每步能跳到的最大位置, 如果能够大于等于数组长度-1 那么就能表示能够跳到。
        for(int i=0;i



45.Jump Game II

Code it now! https://leetcode.com/problems/jump-game-ii/

难度:hard


问题描述:

给定一个非负整数数组,最初定位在数组第一个索引处,数组中每个元素值表示在当前位置所能跳跃的最大长度,确定能够跳到最后一个位置的最少跳跃次数。

假设能够跳到最后一个位置。

解题思路:

  dp算法:时间复杂度O(n^2),空间复杂度O(n)。

 本题使用动态规划策略(最优解的每一个子过程都是当前过程的最优解)。循环遍历数组,并对数组中的元素依次依据前面得到的结果进行优化,大致理解为第n个元素得到的结果是有前n-1个元素所决定的,层层更替结果。代码如下:

 
class Solution {
    public int jump(int[] nums) {
        //备忘录,依次保存跳跃至当前元素所在位置所需要的最少跳跃步数。
        int len = nums.length;
        int[] minJump = new int[len];
        for(int i=0;i= i)
                    minJump[i] = Math.min(minJump[i],minJump[j]+1);
            }
        }
        return minJump[len-1];
    }
}
此算法在LeetCode中超时,因为两层循环遍历效率很低,需要剪枝优化。

  贪心算法:时间复杂度O(n),空间复杂度O(1)。

  本题使用贪心策略,需要在跳跃游戏一当中,进行最小跳跃步数纪录优化操作。代码如下:

 

class Solution {
    public int jump(int[] nums) {
        int curFarthest = 0;
        int curEnd      = 0;
        int step        = 0;
        
        for(int i=0;i



53.Maximum Subarray

Code it now! https://leetcode.com/problems/maximum-subarray/

难度:easy


问题描述:

在一个数组中找到连续的子数组(至少包含一个数字),这个数组的总和最大。简称LIS问题,与其类似的有LCS等问题。

解题思路:

  dp算法:时间复杂度O(n),空间复杂度O(n)。

 本题使用动态规划策略(最优解的每一个子过程都是当前过程的最优解),根据递推公式,写出递推方程为

dp[i] = nums[i]+(dp[i-1]>0?dp[i-1]:0);
 以此公式为核心,不断更新备忘录解集,从而得到最优解。
class Solution {
    public int maxSubArray(int[] nums) {
        int len = nums.length;
        int[] dp = new int[len];
        int max = -1;
        //使用动态规划的记忆化搜索
        for(int i=0;i0?dp[i-1]:0);
            max = Math.max(max,dp[i]);    
        }
        return max;
    }
}


66.Plus One

Code it now! https://leetcode.com/problems/plus-one/

难度:easy


问题描述:

给定一个非负非空数组,整个数组表示一个数,比如nums[0]=1,nums[1]=0,nums[2]=0,整个数组表示数字100然后加一,数组中各个元素相应的发生变化。类似题有给你个String类型数字串, 让你执行加一操作后,返回新的字符串。

该整数不包含任何前导0,就是nums[0]!=0,除非数字0本身。

解题思路:

  遍历算法:时间复杂度O(n),空间复杂度O(1)。

 本题主要考查在加一过程中的进位操作,比如数组表示数字999,那么执行加一操作后整个数字变为1000,也就是数组的大小也增加了一位,数组原来各位元素也发生了相应的改变。若不产生进位,那么在数组末尾元素加一即完成操作。代码如下:

 

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i=digits.length-1;i>=0;i--){
			if(digits[i]+1==10){
				digits[i]=0;
				if(i==0){
					int[] res = new int[digits.length+1];
                    //数组copy函数,digits从下标0开始,res从下标1开始,复制digits.length位数字从digits数组到res数组。
					System.arraycopy(digits, 0, res, 1, digits.length);
					res[0]=1;
					digits = res;
				}
			}else{
                //未产生进位情况,直接在数组最后一个元素加一,break出循环。
				digits[i]++;
				break;
			}
          }
		
		return digits;
    }
}




78.Subsets

Code it now! https://leetcode.com/problems/subsets/

难度:medium


问题描述:

给定一个一组不同元素的整数数组,返回所有可能子集。

解集中子集不可重复。

解题思路:

  回溯算法:时间复杂度O(2^n),空间复杂度O(1)。

 本题用到回溯法(深度优先搜索策略)。

 引入:寻求问题的解的一种可靠方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到需要的解。

 回溯法设计流程是:

 1.定义解向量和每个分量的取值范围,解向量为

  作用:可搜索一个问题的所有解或任一解。

 2.确定每个结点分支的约束条件,即我们需要的解,从所有解当中提取出来。

  作用:从所有检索中,找出满足题意的解。

 3.确定搜索策略:一般是深度优先策略。

 此题为求解子集问题,按照回溯法设计思想进行操作代码如下:

 

class Solution {
    public List> subsets(int[] nums) {
        List> subsets = new  ArrayList>();
        List temp = new ArrayList();
        if(nums.length==0)
            return subsets;
        
        //第一步:定义解向量
        findSubsets(nums,0,temp,subsets);
        return subsets;
    }
    //递归加循环的回溯法。
    public static void findSubsets(int[] nums,int start,List temp,List> subsets){
        //第二步:确定分支条件,选出题目需要的解集
        subsets.add(new ArrayList(temp)); 
        
        //第三步:深度优先搜索
        for(int i=start;i




80.Remove Duplicate from sorted array II

Code it now! https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/

难度:medium


问题描述:

给定有序数组中的重复元素,元素最多允许出现两次,返回新数组长度L,且数组前L个元素有序排列。

不可使用额外空间。

解题思路:

  遍历算法:时间复杂度O(n),空间复杂度O(1)。

 本题用到两指针法,一个用于更新新数组元素,另一个循环遍历数组,代码操作如下,这类题需要一定设计。

 

class Solution {
    public int removeDuplicates(int[] nums) {
        int i=0;
        //i指针用于新数组元素更替,j指针用于快速遍历数组。
        for (int j=0;j nums[i - 2])
            nums[i++] = nums[j];
        }
        return i;
    }
}

  这里也顺便给出只允许元素出现一次的代码操作代码。见leetcode第26题,Remove Duplicate from sorted array.

 

class Solution {
    public int removeDuplicates(int[] nums) {
        /*
        if (nums.length == 0) return 0;
        int i = 0;
        //双指针循环遍历数组。
        for (int j = 1; j < nums.length; j++) {
            if (nums[j] != nums[i]) {
                i++;
                nums[i] = nums[j];
            }
        }
        return i + 1;
    }*/
    //优化版
    int i=0;
    //i指针用于更新新数组元素,j元素用于遍历整个数组。
    for(int j=0;j





442.Find All Duplicates in an Array

Code it now! https://leetcode.com/problems/find-all-duplicates-in-an-array/

难度:medium


问题描述:

给定一个数组元素值在[1,n]之间,一些元素出现两次其它元素出现一次,找出所有重复出现两次的元素。

只能在O(1)空间和O(n)时间复杂度完成。

解题思路:

 元素标记算法:时间复杂度O(n),空间复杂度O(1)。

 本题数组的数据的特点是元素值均在[1,n]之间,这样会有部分元素值是缺失的。 数组下标范围是[0,n-1],我们可以想到的是如果把所有数组元素值-1,那么正好对应数组所有下标,并且使操作得到新下标的元素值为这个新下标的相反数,那么在遍历数组遇到重复元素值的时候,该元素值-1获得的下标所对应的元素值为负数,为我们需要找的目标值。不重复元素,并不会产生这样的冲突,从而出现两次的元素被这种标记思想给挑选了出来。代码如下:

 

class Solution {
    public List findDuplicates(int[] nums) {
        //元素标记法
        List res = new ArrayList();
        for(int i=0;i




448.Find All Numbers Disappeared in an Array

Code it now! https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/

难度:easy


问题描述:

给定一个整数数组,其中1<=a[i]<=n,一些元素出现两次,其它出现一次。

找出在数组[1,n]中没有出现的元素,空间复杂度为O(1),时间复杂度为O(n)。

解题思路:

 元素标记算法:时间复杂度O(n),空间复杂度O(1)。

 本题和442题Find All Duplicates in an Array很相似找出所有重复数字,这里是找出没有出现的数字,因为某些元素出现两次,所以在[1,n]中有部分元素并未出现。本题如果用set集合进行过滤,很便捷就能得到结果,此处空间复杂度限制为O(1),则需要另谋他径。这里也用到的是元素标记法。代码逻辑如下:

 

class Solution {
    public List findDisappearedNumbers(int[] nums) {
        //标记出现过的元素大法。。。
        List list = new ArrayList();
        for(int i=0;i0){
                nums[val] = -nums[val];
            }
        }
        for(int j=0;j0){
                list.add(j+1);
            }
        }
        return list;
    }
}






169.Majority Element

Code it now! https://leetcode.com/problems/majority-element/

难度:easy


问题描述:

给定n个元素的数组,找出出现次数大于一半的元素。

数组非空,且总是有解。

解题思路:

 栈算法:时间复杂度O(n),空间复杂度O(n)。

 本题可使用辅助栈实现,栈的声明是Stack stack = new Stack(),常用栈的几个方法是

 empty():栈是否为空。

 peek():查看栈顶元素,返回该元素。

 push():压入元素至栈顶。

 pop():移除栈顶元素并返回该元素。

 不断往栈中添加和删除元素,当栈为空时,添加当前元素;当栈不为空时,查看当前元素和栈顶元素是否相等,如果想等则继续压入该元素,如果不相等则将栈顶元素弹出。最后栈中仅剩下数组中出现次数大于一半的元素。代码如下:

 

class Solution {
    public int majorityElement(int[] nums) {
        Stack stack = new Stack();
        for(int i=0;i
 
 

 哈希表算法:时间复杂度O(n),空间复杂度O(n)。

 本题也可以使用HashMap实现,使用键值对来统计元素出现次数。涉及到了HashMap的相同key值的value值更新和遍历。代码如下:

 

class Solution {
    public int majorityElement(int[] nums) {
        int result = 0;
	Map map = new HashMap();
        for(int i=0;inums.length/2){
        		result = key;
        	}
        	
        }
	return result;
    }
}

 

 遍历算法:时间复杂度O(n),空间复杂度O(1)。

 使用纯数组操作,用count来计数(用count计数模拟栈操作),详细解释见注释。

class Solution {
    public int majorityElement(int[] nums) {   
        int count = 0;
        int res = -1;
        for(int i=0;i






229.Majority Element II

Code it now! https://leetcode.com/problems/majority-element-ii/

难度:medium


问题描述:

给定n个元素的数组,找出所有出现超过n/3的元素。

算法需要在线性时间和O(1)空间中运行。

解题思路:

 栈算法:时间复杂度O(n),空间复杂度O(1)。

 本题和169题Majority Element有着很大的不同,是否存在共性的方法呢?前面没有空间限制,处理的用到了栈和Hashmap辅助空间来实现。本题用HashMap还是很容易实现,这里不可行;对数组排序,双指针也能很快求出,仍然不可行!!!于是169题应有空间复杂度O(1)的方法(已追加)。169题使用count来对出现次数超过1/2的数进行计数,类比过来,超过n/3的元素在数组中可能有1个或者是2个,我们使用count1和count2两个计数器进行计数,(仔细想想不难发现,如果假设数组有90个元素,满足条件的元素至少需要出现31次,因为有count1和count2计数器,数组元素的计数变成了count1处理45个元素,count2处理45个元素,在45个元素中出现31次是过半的,因此符合169题的寻找过半元素操作,一番操作下来,原问题转化成了把数组分成两半,在各自一半中寻找过半元素。没错,就是这样!),因此同样可以起到过滤作用,筛选出我们可能需要的元素,再通过一层循环判断是否为我们需要的结果即可。代码如下:

 

class Solution {
    public List majorityElement(int[] nums) {
        if(nums.length==0)
            return new ArrayList();
        List res = new ArrayList();
        int number1 = nums[0];
        int number2 = nums[0];
        int count1  = 0;
        int count2  = 0;
        for(int i=0;inums.length/3)
            res.add(number1);
        if(count2>nums.length/3)
            res.add(number2);
        return res;
    }
}
 





215.Kth Largest Element in an Array

Code it now! https://leetcode.com/problems/kth-largest-element-in-an-array/

难度:medium


问题描述:

在未排序数组中找到第K大的元素,1<=K<=nums.length。

排序中第K大的元素,不是第K个位置元素;那么假设数组为{1,2,3,4,5,5},那么数字2算是第几大呢? 在本题中数字2属于第5大,不是第4大。可以理解成如果这个数组有序,第K大元素为从后往前数,数K个位置所对应的元素。

解题思路:

 排序算法:时间复杂度O(nlog n),空间复杂度O(1)。

 对数组进行排序,并输出相应位置,无脑做法,代码如下:

 

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length-k];
    }
}
 

 分治算法:时间复杂度O(n),空间复杂度O(1)。

 显然本题不是通过排序投机取巧来处理,比较好理解的是分治算法来处理,我们需要找的是第K大元素,我们把问题等价转换成找第N-K+1小问题。在快速排序思想中我们知道,每次都能至少确定某个元素位置(一般以数组第一个元素作为中间值),于是本题就是利用了这种方式操作的,代码如下:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return findKth(nums,0,nums.length-1,nums.length-k+1);     
    }
    //可类比快速排序中取得partion值的算法过程
    public static int findKth(int[] nums,int l,int r,int k) {
        int p     = l;
        int left  = l;
        int right = r;
        //把整个数组依据数组第一个元素值进行划分成两块,左边都小于该值,右边都大于该值。
        while(left=nums[p])
                right--;
            while(left 

  上面算法的过程可进一步升级成BFPRT算法,因为这里每次取做中间值的元素都是数组第一个元素,显然在糟糕情况下,算法的效率还是堪忧。BFPRT的核心思想就是在选取做中间值元素的时候选取了五分中位数的中位数作为中间值,能够保证此算法能够在线性时间得到需要的结果。有兴趣的可以自行百度BFPRT,哈哈哈哈哈。





414.Third Maximum Number

Code it now! https://leetcode.com/problems/third-maximum-number/

难度:easy


问题描述:

给定一个非空数组,返回数组第三大元素,如果不存在则返回最大元素。

时间复杂度一定为O(n),数组中可能有存在重复元素。

解题思路:

 排序算法:时间复杂度O(n),空间复杂度O(1)。

 本题和215题Kth Largest Element in an Array非常相似,但是不可直接用215的方法进行求解,需要对本题所给数组进行去重处理。在去重后的新数组中,首先判断新数组元素个数,对于小于等于2个元素的数组先进行预处理,方可使用分治算法进行求解。本人用了个很蠢的办法进行拼接求解。第一步,去除数组中重复元素(因为数组无序,以前有道题所用到的双指针创造一个无重复数字的数组不可实现,用了set去重!!!很蠢);第二步,利用到冒泡排序思想,上浮三次即可找到第三大元素。整体时间复杂度为O(n),代码如下:

 

class Solution {
    public int thirdMax(int[] nums) {
        int temp = 0;
        int count = 0;
        int j = 0;
        Set set = new HashSet();
        for(int i=0;inums[i+1]){
                       temp = nums[i];
                       nums[i] = nums[i+1];
                       nums[i+1] = temp;
                   }
               }
              count++;   
        }
        return nums[set.size()-3];   
    }
}

  这个方法很蠢,但是总算顺利求解,好办法加载中。。。






665.Non-decreasing Array

Code it now! https://leetcode.com/problems/non-decreasing-array/

难度:easy


问题描述:

给定一个有n个整数的数组,你的任务是通过至多修改一个元素来检查该数组是否可以不减少。

非递减数组。

解题思路:

 排序算法:时间复杂度O(n),空间复杂度O(1)。

 本题简单的挨个前后元素统计是否存在逆序,如果逆序小于等于1则认为可调整,大于1认为不可调整是错误的。假设数组为{5,6,1,2,3,4,5,6},前后产生逆序只有一次,但是不可通过只修改一个元素来实现数组为非递减数组。于是乎,我们在判断前后元素大小关系时,还需要对元素位置进行一定调整。于是我们想到,如果以i下标做基准,i-1的元素值大于i+1元素时,此时需要令第i+1位置的元素值赋值为i-1位置的值,然后继续进行数组是否还有逆序,如果不大于则令i的元素值等于i+1位置的元素值。{5,6,1,2,3,4,5,6}和{5,6,4,7,8,9} 从这两个数组我们能够模拟出为什么我们要这样调整。避免产生错误结果。代码如下:

 

class Solution {
    public boolean checkPossibility(int[] nums) {
        int len = nums.length;
        int count = 0;
        for(int i=0;i+1nums[i+1]){
                count++;
            //对产生逆序的元素进行处理,3 4 2 3  当i=1,且nums[2]nums[0]则令nums[1]=nums[2]
            //先进行处理保持当前元素继续有序之后(调整位置),再继续查找是否还存在逆序现象,如果还存在则会令count增加。  
            if(i>0&&nums[i-1]>nums[i+1]) 
            {
                nums[i+1] = nums[i];
            }else{
                nums[i] = nums[i+1];
            }
        }
        }
        return count<=1;
    }
}







665.待追加。。。

Code it now! https://leetcode.com/problems/non-decreasing-array/

难度:easy


问题描述:

给定一个有n个整数的数组,你的任务是通过至多修改一个元素来检查该数组是否可以不减少。

非递减数组。

解题思路:

 排序算法:时间复杂度O(n),空间复杂度O(1)。

 本题简单的挨个前后元素统计是否存在逆序
















 

 





 

 









 














































   

你可能感兴趣的:(Leetcode)