leetcode之分治刷题总结1
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode之分治刷题总结1相关的知识,希望对你有一定的参考价值。
leetcode之分治刷题总结1
1-多数元素
题目链接:题目链接戳这里!!!
思路1:因为多数元素就一个,直接升序排序,返回中间那个值,一定是升序元素。
class Solution
public int majorityElement(int[] nums)
Arrays.sort(nums) ;
return nums[nums.length/2];
思路2:借助HashMap,存储每个数字出现的次数,出现次数大于n/2,则该数字就是多数元素。
class Solution
public int majorityElement(int[] nums)
Map<Integer, Integer> map = new HashMap<>() ;
int mid = nums.length / 2 ;
for(int i=0; i<nums.length; i++)
int count = map.getOrDefault(nums[i],0)+1 ;
if(count>mid)
return nums[i];
map.put(nums[i],count) ;
return nums[nums.length-1] ;
思路3:分治思想,效率更高。
因为我们要找的是多数元素,那么我们将数组分成两部分,则至少有一部分的多数元素和数组的多数元素相同,那么这样,我们就可以用分治的思想了,递归求出左半数组的多数元素和右半数组的多数元素,如果二者相同,则该数就是数组的多数元素,如果不同,需要比较二者在数组中出现的次数,出现次数多的为多数元素。
AC代码如下:
class Solution
public int majorityElement(int[] nums)
return split(nums, 0, nums.length-1) ;
public int split(int [] nums, int left, int right)
if(left==right)
return nums[left] ;
int mid = (left+right)>>1 ;
int leftMajor = split(nums,left,mid) ;
int rightMajor = split(nums,mid+1,right) ;
if(leftMajor==rightMajor)
return leftMajor ;
return merge(nums, leftMajor, rightMajor, left, right) ;
public int merge(int [] nums, int leftMajor, int rightMajor, int left, int right)
int countLeft = 0, countRight = 0 ;
for(int i=left; i<=right; i++)
if(nums[i]==leftMajor)
countLeft ++ ;
if(nums[i]==rightMajor)
countRight ++ ;
return Math.max(countRight,countLeft)==countLeft ? leftMajor : rightMajor ;
2-寻找两个正序数组中的中位数
题目链接:题目链接戳这里!!!
思路1:直接合并为一个数组,升序排序,找出中位数即可。该方法虽然能AC,但是时间复杂度O(n)。
AC代码如下:
class Solution
public double findMedianSortedArrays(int[] nums1, int[] nums2)
int m = nums1.length ;
int n = nums2.length ;
int [] arr = new int [m+n] ;
for(int i=0; i<m; i++)
arr[i] = nums1[i] ;
for(int i=m; i<m+n; i++)
arr[i] = nums2[i-m] ;
Arrays.sort(arr) ;
if((arr.length&1) == 1)
return arr[(m+n)/2] ;
else
return 1.0 * (arr[(m+n)/2]+arr[(m+n)/2-1]) / 2 ;
3- 数组中的第K个最大元素
题目链接:题目链接戳这里!!!
思路1:直接调库排序,然后输出第K大的就可以。这个效率已经很高了。
class Solution
public int findKthLargest(int[] nums, int k)
Arrays.sort(nums) ;
return nums[nums.length - k] ;
思路2:快速排序法
快排是基于分治的思想,将数组分成两部分,将大于主元的放在右边,小于主元的放到左边,然后对左右进行递归排序,如果主元的下标等于nums.length-k则说明找到了,否则根据主元的位置,对左边数组或者右边数组继续排序。
效率杠杠滴!!!
class Solution
public int findKthLargest(int[] nums, int k)
return quickSort(nums, 0, nums.length-1, nums.length-k) ;
public int quickSort(int []nums, int left, int right, int idx)
int q = partition(nums, left, right) ;
if(q>idx)
return quickSort(nums,0,q-1,idx) ;
else if(q<idx)
return quickSort(nums,q+1,right,idx) ;
else
return nums[idx] ;
public int partition(int [] arr, int p, int r)
int idx = (int) (Math.random()*(r-p+1)) + p ;
swap(arr, idx, p) ;
int pivot = arr[p] ; //初始化主元
int left = p + 1; //左侧扫描指针
int right = r ; //右侧扫描指针
while(left <= right)
while(left <= right && arr[left] <= pivot)
left ++ ;
while(left <= right && arr[right] >= pivot)
right -- ;
if(left < right) //找到左侧比主元大的,右侧比主元小的,二者交换
swap(arr, left, right) ;
swap(arr, p, right) ; //将初始化的主元与划分后得到的主元交换
return right ;
public void swap(int []arr, int i, int j)
int temp = arr[i] ;
arr[i] = arr[j] ;
arr[j] = temp ;
4-摆动序列II
题目链接:题目链接戳这里!!!
思路:直接采用插孔的方式,先升序排序,然后然后从从往前选元素,依次插孔。
class Solution
public void wiggleSort(int[] nums)
Arrays.sort(nums) ;
int [] array = new int [nums.length] ;
int k=nums.length-1;
for(int i=1;i<nums.length;i+=2)
array[i]=nums[k--];
for(int i=0;i<nums.length;i+=2)
array[i]=nums[k--];
for(int i=0; i<array.length; i++)
nums[i] = array[i] ;
5-环形子数组的最大和
题目链接:题目链接戳这里!!!
思路:分为跨边界和没有跨边界两种情况。
如果没有跨界,依次遍历,找出最大和即可。
如果跨边界,需要记录总和减取最小和。
AC代码如下:
class Solution
public int maxSubarraySumCircular(int[] nums)
//分为跨边界和没跨边界两种情况
int curMin, curMax, min, max, sum ;
curMax = curMin = max = min = sum = nums[0] ;
for(int i=1; i<nums.length; i++)
sum += nums[i] ;
curMax = curMax>0 ? curMax+nums[i] : nums[i] ;
max = Math.max(max, curMax) ;
curMin = curMin<0 ? curMin+nums[i] : nums[i] ;
min = Math.min(min, curMin) ;
if(max<0)
return max ;
return Math.max(max, sum-min) ;
6-前K个高频元素
题目链接:题目链接戳这里!!!
思路1:用HashMap记录每个数字出现的次数,找到出现次数最多的,再通过HashMap依次对比输出出现次数前K多的元素即可。
AC代码如下:
class Solution
public int[] topKFrequent(int[] nums, int k)
Map<Integer,Integer> map = new HashMap<>() ;
for(int i=0; i<nums.length; i++)
map.put(nums[i],map.getOrDefault(nums[i],0)+1) ;
int maxTimes = 0 ;
for(Map.Entry<Integer,Integer> entry : map.entrySet())
if(entry.getValue()>=maxTimes)
maxTimes = entry.getValue() ;
int [] res = new int [k] ;
while(k>0)
for(Map.Entry<Integer,Integer> entry : map.entrySet())
if(entry.getValue()==maxTimes)
res[k-1] = entry.getKey();
k -- ;
maxTimes -- ;
return res ;
思路2:基于快速排序的解法
思路如图所示,不过是把大的放到arr[q]左面,小的放到arr[q]右面.
class Solution
public int[] topKFrequent(int[] nums, int k)
Map<Integer,Integer> map = new HashMap<>() ;
for(int i=0; i<nums.length; i++)
map.put(nums[i],map.getOrDefault(nums[i],0)+1) ;
List<int[]> list = new ArrayList<>() ;
for(Map.Entry<Integer,Integer> entry : map.entrySet())
list.add(new int[]entry.getKey(),entry.getValue()) ;
int [] res = new int [k] ;
quickSort(list, 0, list.size()-1, res, 0, k) ;
return res ;
public void quickSort(List<int[]>list, int start, int end, int [] res, int resIndex, int k)
int p = (int)(Math.random()*(end-start+1)) + start ;
Collections.swap(list,p,start) ;
int pivot = list.get(start)[1] ;
int idx = start ;
for(int i=start+1; i<=end; i++)
if(list.get(i)[1]>=pivot)
Collections.swap(list,i,idx+1) ;
idx ++ ;
Collections.swap(list, start, idx) ;
if(k <=idx-start)
quickSort(list, start, idx-1, res, resIndex, k) ;
else
for(int i=start; i<=idx; i++)
res[resIndex++] = list.get(i)[0] ;
if(k>idx-start+1)
quickSort(list,idx+1, end, res, resIndex, k-(idx-start+1)) ;
leetcode之模拟刷题总结1