[Algorithm]九章七:Two Pointer
604. Window Sum:点击打开链接
例如:[1,2,7,8,5], k=3
sum[0]=nums[0]+nums[1]+nums[2]=10
sum[1]=sum[0]-nums[0]+nums[0+3]=17,也就是说sum[1]=10-1+8
sum[2]=sum[1]-nums[1]+nums[1+3]=20,也就是说sum[2]=17-2+5
窗口向后滑动,要减去(滑出窗口里的值),同时加上(滑入窗口里的值)
public class Solution {/*** @param nums a list of integers.* @return the sum of the element inside the window at each moving.*/public int[] winSum(int[] nums, int k) {if(nums==null || nums.length==0){return new int[0];}if(k<=0){return new int[0];}int[] sum=new int[nums.length-k+1]; for(int i=0;i<k;i++){ //i<ksum[0]+=nums[i];}for(int i=1;i<sum.length;i++){ //i<sum.length,不然数组越界异常sum[i]=sum[i-1]-nums[i-1]+nums[i-1+k];}return sum;}
}
539. Move Zeros:点击打开链接
public class Solution {/*** @param nums an integer array* @return nothing, do this in-place*/public void moveZeroes(int[] nums) {int j=0;for(int i=0;i<nums.length;i++){ //i从头开始遍历,当值不为0就和第一个交换位置,再有值不为0,和第一个的后一个交换if(nums[i]!=0){ //即使开始的值不为0,也不影响,因为相当于自己和自己交换int temp=nums[i]; //例如:[1,2,0,3,4],开始交换的时候1,2的位置不变,值为3的时候和0交换,4同理nums[i]=nums[j];nums[j]=temp;j++;}}}
}
public class Solution {/*** @param nums an integer array* @return nothing, do this in-place*/public void moveZeroes(int[] nums) { //为什么这种做法不行?int j=nums.length; //i从头开始遍历,当值为0就和最后一个数交换位置,再有值为0,和最后一个的前一个交换for(int i=0;i<nums.length;i++){ //因为这种做法可能最后一个位置的值是0if(nums[i]==0){ //例如:[0,1,0,1,3,0],开始交换的时候只是头和尾两个0交换了位置,所以不对 int temp=nums[i];nums[i]=nums[j];nums[j]=temp;j--;}}}
}
521.Remove Duplicates from Sorted Array:点击打开链接
public class Solution {/*** @param nums an array of integers* @return the number of unique integers*/public int deduplication(int[] nums) { //例如:[1,3,1,4,4,2]if(nums==null || nums.length==0){return 0;}Arrays.sort(nums); //[1,1,1,2,3,4,4] int index=1;for(int i=1;i<nums.length;i++){ //就让第一个值不动,从第二个值开始,依次与前一个值比较if(nums[i]!=nums[i-1]){ //如果两者不相等,后者值和index++位置的值交换位置nums[index++]=nums[i];}}return index;}
}
public class Solution {/*** @param nums an array of integers* @return the number of unique integers*/public int deduplication(int[] nums) { //方法二if(nums==null || nums.length==0){return 0;}Arrays.sort(nums); //解题前要看题目给出的数组是不是有序数组,不是的话要排序int i=0; //是否排序也要看题目要求,如果让输出符合条件的索引,不可以排序for(int n:nums){if(i<1 || n!=nums[i-1]){nums[i++]=n;}}return i;}
}
101. Remove Duplicates from Sorted Array II:点击打开链接
思路:当i=0时,nums[0]还是本身
当i=1时,nums[1]也还是本身,因为不管nums[1]是否等于nums[0]都没关系,因为题目说最多可以有两个duplicates
从i=2开始,开始判断nums[i-2]!=n,也就是说nums[0]!=nums[2],其实就是判断这个数与否等于它前两位的那个数,
如果不等于,符合题目要求,当前数有效,不移除。
public class Solution {/*** @param A: a array of integers* @return : return an integer*/public int removeDuplicates(int[] nums) {if(nums==null || nums.length==0){return 0;}int i=0; //例如{3,3,4,5,5,6}for(int n:nums){ //在i=0,i=1的时候已经和数组用n表示的前两个数比较过if(i<2 || n!=nums[i-2]){ //i=2的时候,n!=nums[i-2]表示的是4!=nums[0]nums[i++]=n; }}return i;}
}
8.Rotate String:点击打开链接
例如:char[] str=[a,b,c,d,e,f,g],offset=3
Output: [e,f,g,a,b,c,d]
三步翻转法:
1. [g,f,e,d,c,b,a],整个大翻转
2. [e,f,g,d,c,b,a], e,f,g翻转
3. [e,f,g,a,b,c,d], a,b,c,d翻转
注意:先整个大翻转的必要性,一般来说,由于往前放的位数少,因此先进行整个大翻转会省时
当然也可以先局部翻转,再整个大翻转
要看具体题目要求,是要在原来有序的数组上后面几个元素翻转到前面,还是已经翻转好的要恢复有序数组
也就是说,是要[a,b,c,d,e,f,g]->[e,f,g,a,b,c,d],还是[e,f,g,a,b,c,d]恢复成[a,b,c,d,e,f,g]
public class Solution {/*** @param str: an array of char* @param offset: an integer* @return: nothing*/public void rotateString(char[] str, int offset) {if(offset==0){return;}if(str==null || str.length==0){return;}int n=str.length;offset=offset%n;reverse(str,0,n-1);reverse(str,0,offset-1);reverse(str,offset,n-1);}private void reverse(char[] str,int start,int end){while(start<end){char temp=str[start]; //char tempstr[start]=str[end]; str[end]=temp;start++;end--;}}
}
39.Recover Rotated Sorted Array :点击打开链接
题意:这题就是要恢复成有序arraylist,例如:[4,5,1,2,3]->[1,2,3,4,5]
思路:从5和1这个位置入手,遍历整个list的值,只要前一个值比后一个值大,就找到了5和1,然后j进行三步翻转
注意:reverse方法对一个arraylist进行reverse,因此用了方法arraylist.set()
public class Solution {/*** @param nums: The rotated sorted array* @return: void*/public void recoverRotatedSortedArray(ArrayList<Integer> nums) {if(nums==null || nums.size()==0){return;}int k=0;for(int i=0;i<nums.size()-1;i++){if(nums.get(i)>nums.get(i+1)){k=i;reverse(nums,0,k);reverse(nums,k+1,nums.size()-1);reverse(nums,0,nums.size()-1);}}}private void reverse(ArrayList<Integer> nums,int start,int end){while(start<end){int temp=nums.get(start);nums.set(start,nums.get(end)); //nums.set()nums.set(end,temp);start++;end--;}}
}
56.Two Sum:点击打开链接
下面就是经典题型Two Sum和它的一系列follow ups
对于Two Sum一般有两种做法:HashMap和Two Pointers
public class Solution {/** @param numbers : An array of Integer* @param target : target = numbers[index1] + numbers[index2]* @return : [index1 + 1, index2 + 1] (index1 < index2)*/public int[] twoSum(int[] numbers, int target) { //HashMap方法int[] result=new int[2];if(numbers==null ||numbers.length==0){return result;}Map<Integer,Integer> map=new HashMap<>(); //例如:[2,7,11,15],target=9for(int i=0;i<numbers.length;i++){if(!map.containsKey(target-numbers[i])){ //遍历数组,一开始nums[0]=2,map里没有7,放入<2,0>map.put(numbers[i],i);}else{ //往下遍历到nums[1]=7,map里有2,result[0]=map.get(target-numbers[i])+1; //就把2和7所对应的索引加入到result list里result[1]=i+1; //由于题目要求result不是zero-based,所以每个索引值+1}}return result;}
}
608.Two Sum-Input array is Sorted:点击打开链接
public class Solution {/** @param nums an array of Integer* @param target = nums[index1] + nums[index2]* @return [index1 + 1, index2 + 1] (index1 < index2)*/public int[] twoSum(int[] nums, int target) { //双指针法:适合可以sort的数组int[] result=new int[2];if(nums==null || nums.length==0){return result;}int start=0;int end=nums.length-1;while(start<end){ //因为最后要有start和end两个数,因此不能start<=endif(nums[start]+nums[end]<target){ start++;}else if(nums[start]+nums[end]>target){end--;}else{result[0]=start+1; //注意好题目要求是non zero-based,还是zero-basedresult[1]=end+1;return result;}}return null;}
}
607.Two Sum-Data Structure Design:点击打开链接
public class TwoSum { //只能使用HashMap的private List<Integer> list=null;private Map<Integer,Integer> map=null;public TwoSum(){list=new ArrayList<>();map=new HashMap<>();}// Add the number to an internal data structure.public void add(int number) {// Write your code hereif(!map.containsKey(number)){map.put(number,1);list.add(number);}else{map.put(number,map.get(number)+1);}}// Find if there exists any pair of numbers which sum is equal to the value.public boolean find(int value) {for(int i=0;i<list.size();i++){int nums1=list.get(i);int nums2=value-nums1;if(nums1==nums2 && map.get(nums1)>1){return true;}if(nums1!=nums2 && map.containsKey(nums2)){return true;}}return false;}
}// Your TwoSum object will be instantiated and called as such:
// TwoSum twoSum = new TwoSum();
// twoSum.add(number);
// twoSum.find(value);
587.Two Sum-Unique pairs:点击打开链接
public class Solution {/*** @param nums an array of integer* @param target an integer* @return an integer*/public int twoSum6(int[] nums, int target) {if(nums==null || nums.length<0){return 0;}Arrays.sort(nums);int start=0,end=nums.length-1;int count=0;while(start<end){if(nums[start]+nums[end]==target){start++;end--;count++; while(start<end && nums[start]==nums[start-1]){ //当有一对和为target的数时,看start的后面的数是否与start等start++; //如果等,就要往前走以便略过这个相同的数}while(start<end && nums[end]==nums[end+1]){ //也要看end的前面的数时候与end等end--; //如果等,就要end--方式向前走以便略过这个相同的数}}else if(nums[start]+nums[end]>target){end--;}else{start++;}}return count;}
}
609. Two Sum-Less than or equal to target: 点击打开链接
例如:[2,7,11,15],target=24
思路:当2+15<24,15是最大值都小于target了,2+7,2+11一定也小于,两数对应的索引相减3-0=3,这段区间有3对数符合要求,start++
再看[2,7,11,15]这段区间,同理有3-1=2对数符合要求,start++
再看[2,7,11,15]这段区间, 11+15>target,end--
public class Solution {/*** @param nums an array of integer* @param target an integer* @return an integer*/public int twoSum5(int[] nums, int target) {if(nums==null || nums.length==0){return 0;}Arrays.sort(nums);int count=0;int start=0,end=nums.length-1;while(start<end){if(nums[start]+nums[end]<=target){count+=end-start;start++;}else{end--;}}return count;}
}
443.Two Sum-Greater than target:点击打开链接
public class Solution {/*** @param nums: an array of integer* @param target: an integer* @return: an integer*/public int twoSum2(int[] nums, int target) { //和小于等于target的正好相反if(nums==null ||nums.length==0){return 0;}Arrays.sort(nums);int count=0;int start=0,end=nums.length-1;while(start<end){if(nums[start]+nums[end]<=target){ //如果小于等于target,start++start++;}else{ //直到大于target,这段区间符合条件的对数是:区间前后索引之差 count+=end-start;end--; //end--}}return count;}
}
610.Two Sum-Difference equals to target:点击打开链接
例如:[2,7,15,14],target=5
思路:遍历数组,但是每个值都要查看nums[i]+target和nums[i]-target 两种情况
public class Solution {/** @param nums an array of Integer* @param target an integer* @return [index1 + 1, index2 + 1] (index1 < index2)*/public int[] twoSum7(int[] nums, int target) {int[] result=new int[2];if(nums==null || nums.length==0){return result;}Map<Integer,Integer> map=new HashMap<>();for(int i=0;i<nums.length;i++){int diff1=nums[i]-target;int diff2=nums[i]+target;if(!map.containsKey(diff1) && !map.containsKey(diff2)){map.put(nums[i],i);}else if(map.containsKey(diff1)){result[0]=map.get(diff1)+1;result[1]=i+1;break;}else if(map.containsKey(diff2)){result[0]=map.get(diff2)+1;result[1]=i+1;break;}}return result;}
}
57. 3Sum:点击打开链接
例如:[-1,0,1,2,-1,-4]
思路:a+b+c=0,-a=b+c
遍历数组里的每一个数nums[i],对于每一个数,都从i+1~nums.length-1区间来找另外两个数,
使得-nums[i]=nums[i+1]+nums[nums.length-1],也就是nums[i]+nums[i+1]+nums[nums.length-1]=0
注意:1. 用Two Pointers方法一定要先Arrays.sort()数组
2. 对于nums[i],nums[i+1]和nums[length-1]都要判断是不是与前一个数相等
public class Solution {/*** @param numbers : Give an array numbers of n integer* @return : Find all unique triplets in the array which gives the sum of zero.*/public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) {ArrayList<ArrayList<Integer>> result=new ArrayList<>();if(numbers==null || numbers.length<3){ //只要numbers.length<3就不符合题意了return result;}Arrays.sort(numbers);for(int i=0;i<numbers.length-1;i++){if(i>0 && numbers[i]==numbers[i-1]){ //对于每一个a都要判断是不是和前一个相等continue;}int target=-numbers[i];int start=i+1;int end=numbers.length-1;twoSum(numbers,start,end,target,result);}return result;}private void twoSum(int[] nums,int start,int end,int target,ArrayList<ArrayList<Integer>> result){while(start<end){if(nums[start]+nums[end]==target){ArrayList<Integer> list=new ArrayList<>();list.add(-target);list.add(nums[start]);list.add(nums[end]);result.add(list);start++;end--;while(start<end && nums[start]==nums[start-1]){ start++;}while(start<end && nums[end]==nums[end+1]){end--;}}else if(nums[start]+nums[end]<target){start++;}else{end--;}}}
}
例如:[1,1,2,3,4,5,6],target=9
1. i从0向后遍历
2. 第一轮i=0,start=1,end=6,因为开始小于9,所以start++到start=2,此时1+2+6=9,
完成装到result后,start和end还会移动,找其他满足条件的组合,以上是一个完整的第一轮,然后才开始第二轮
3. 第二轮i=1,start=1,end=6,此时1+2+6=9
因为被遍历的i与它前一个数相等,因此会以continue的方法跳出本次,因为这样的情况下会输出重复组合
4. 第三轮i=2
public class Solution {/*** @param numbers : Give an array numbers of n integer* @return : Find all unique triplets in the array which gives the sum of zero.*/public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) { //方法二:直接看当前三个数的和是不是等于0ArrayList<ArrayList<Integer>> result=new ArrayList<>(); //个人感觉这个方法更直接,更容易弄懂if(numbers==null || numbers.length<3){return result;}Arrays.sort(numbers);for(int i=0;i<numbers.length-1;i++){if(i>0 && numbers[i]==numbers[i-1]){ //如果i重复continue; //跳出本次i,进入for循环里的下一个i}int start=i+1;int end=numbers.length-1;while(start<end){int sum=numbers[i]+numbers[start]+numbers[end];if(sum==0){ArrayList<Integer> list=new ArrayList<>();list.add(numbers[i]);list.add(numbers[start]);list.add(numbers[end]);result.add(list);start++;end--;while(start<end && numbers[start]==numbers[start-1]){//如果start重复start++;}while(start<end && numbers[end]==numbers[end+1]){ //如果end重复end--;}}else if(sum<0){start++;}else{end--;}}}return result;}
}
923. 3Sum With Multiplicity
public int threeSumMulti(int[] A, int target) {int mol = 1000000007; // 如果写成10^9+7的形式,就过不了,Bitwise Operators Arrays.sort(A);int res = 0;Map<Integer, Long> map = new HashMap<>();for (int i = 0; i < A.length; ++i) {map.put(A[i], map.getOrDefault(A[i], 0l) + 1l);}for (int i = 0; i < A.length; i++) {if (i > 0 && A[i] == A[i - 1]) {continue;}int start = i + 1, end = A.length - 1;while (start < end) {if (A[i] + A[start] + A[end] < target) {start++;}else if (A[i] + A[start] + A[end] > target) {end--;}else {if (A[i] == A[start] && A[start] == A[end]) {res += (map.get(A[i])) * (map.get(A[i]) - 1) * (map.get(A[i]) - 2) / 6 % mol;}else if (A[i] == A[start]) {res += (map.get(A[i])) * (map.get(A[i]) - 1) / 2 * (map.get(A[end])) % mol;}else if (A[start] == A[end]) {res += (map.get(A[i])) * (map.get(A[start])) * (map.get(A[start]) - 1) / 2 % mol;}else {res += map.get(A[i]) * map.get(A[start]) * map.get(A[end]) % mol;}start++;end--;while (start<end && A[start] == A[start-1]){start++;}while (start<end && A[end] == A[end+1]) {end--;} }}}return res;
259. 3Sum Smaller
Given an array of n integers nums and a target, find the number of index triplets i, j, k
with 0 <= i < j < k < n
that satisfy the condition nums[i] + nums[j] + nums[k] < target
.
Example:
Input: nums = [-2,0,1,3]
, and target = 2
Output: 2
Explanation: Because there are two triplets which sums are less than 2:[-2,0,1][-2,0,3]
Note: 以[-2, 0, 1, 3]作为example , nums[i] =-2,,nums[start]=0,,nums[end]=3,,当-2+0+3<target时,如果采用start++来判断, 此时nums[start]=1, 所以走向一直是start向右移动,会漏掉end应该向左移动的cases
class Solution {public int threeSumSmaller(int[] nums, int target) {int result = 0;if(nums==null || nums.length == 0){return result;}Arrays.sort(nums);for(int i=0; i<nums.length-1; i++){int start= i+1;int end= nums.length-1;while(start < end){if(nums[i] + nums[start] + nums[end] < target ){ int count = end-start; //这边不能一个一个走,原因是只单向移动start,会漏掉end符合条件的情况result += count;start++;}else{end--;} }} return result;}
}
382.Triangle Count:点击打开链接
例如:[3,4,6,7],Output:3
思路:sort数组后,i从后向前遍历数组,遍历的值nums[i]作为第三条边a,而nums[0]和nums[i-1]作为另两边b,c
因此如果满足b+c>a,就是一个三角形。
同时要注意,如果此时的b+c>a,得知(b后面的数)+c>a一定成立,所以直接加上这一段的有效三角形个数,然后end--;
如果b+c<a,就start++;
注意:此题的遍历方向
public class Solution {/*** @param S: A list of integers* @return: An integer*/public int triangleCount(int S[]) {if(S==null || S.length<3){return 0;}Arrays.sort(S);int count=0;for(int i=S.length-1;i>0;i--){ //数组从后往前倒着遍历int start=0;int end=i-1;while(start<end){if(S[start]+S[end]>S[i]){count+=end-start;end--;}else{start++;}}}return count;}
}
533.Two Sum-Closet to target: 点击打开链接
思路:还是 Two Sum双指针法,只是每次都要记录target与当前nums[start]+nums[end]的差值,并更新成最小的closet值,也就是最closet的。
public class Solution {/*** @param nums an integer array* @param target an integer* @return the difference between the sum and the target*/public int twoSumClosest(int[] nums, int target) {if(nums==null || nums.length<0){return 0;}Arrays.sort(nums);int start=0,end=nums.length-1;int closet=Integer.MAX_VALUE;while(start<end){if(nums[start]+nums[end]==target){ //如果nums[]+nums[]==targetcloset=0; //此时就是最理想的情况,要returnreturn closet;}else if(nums[start]+nums[end]<target){closet=Math.min(closet,target-nums[start]-nums[end]);start++;}else{closet=Math.min(closet,nums[start]+nums[end]-target);end--;}}return closet;}
}
public class Solution {/*** @param nums an integer array* @param target an integer* @return the difference between the sum and the target*/public int twoSumClosest(int[] nums, int target) { //或者用和3Sum Closet通用方法if(nums==null || nums.length<0){return 0;}Arrays.sort(nums);int start=0,end=nums.length-1;int closet=Integer.MAX_VALUE;while(start<end){int diff=nums[start]+nums[end]-target;if(Math.abs(diff)<closet){closet=Math.abs(diff);}if(diff==0){closet=0;return closet;}else if(diff<0){start++;}else{end--;}}return closet;}
}
59.3Sum Closet:点击打开链接
public class Solution {/*** @param numbers: Give an array numbers of n integer* @param target : An integer* @return : return the sum of the three integers, the sum closest target.*/public int threeSumClosest(int[] numbers, int target) {if(numbers==null || numbers.length<3){return 0;}Arrays.sort(numbers);int sum=0;int closet=Integer.MAX_VALUE;for(int i=0;i<numbers.length;i++){int start=i+1;int end=numbers.length-1;while(start<end){int diff=numbers[start]+numbers[end]+numbers[i]-target; //先记录当前要用的三个数与target的差值if(Math.abs(diff)<closet){ //每次都要比较当前绝对差值与closet的大小closet=Math.abs(diff); //更新closet值sum=numbers[start]+numbers[end]+numbers[i]; //并记录当前最小closet情况下的的sum}if(diff==0){ //差值为0就是最理想情况,此时要return closetreturn sum;}else if(diff>0){end--;}else{start++;}}}return sum;}
}
58.4Sum:点击打开链接
思路:和3Sum想法一样,不同点在于循环遍历两个数,另外两个数一个是start,一个是end
注意:题目要求输出list里不能包括重复的小list,因此循环遍历的两个数分别要检查是不是和后面的数相等
public class Solution {/*** @param numbers : Give an array numbersbers of n integer* @param target : you need to find four elements that's sum of target* @return : Find all unique quadruplets in the array which gives the sum of* zero.*/public ArrayList<ArrayList<Integer>> fourSum(int[] numbers, int target) {ArrayList<ArrayList<Integer>> result=new ArrayList<>();if(numbers==null || numbers.length<4){return result;}Arrays.sort(numbers);for(int i=0;i<numbers.length-1;i++){ if(i>0 && numbers[i]==numbers[i-1]){continue;}for(int j=i+1;j<numbers.length;j++){if(j!=i+1 && numbers[j]==numbers[j-1]){continue;}int start=j+1;int end=numbers.length-1;while(start<end){int sum=numbers[i]+numbers[j]+numbers[start]+numbers[end];if(sum>target){end--;}else if(sum<target){start++;}else{ArrayList<Integer> list=new ArrayList<>();list.add(numbers[i]);list.add(numbers[j]);list.add(numbers[start]);list.add(numbers[end]);result.add(list);start++;end--;while(start<end && numbers[start]==numbers[start-1]){start++;}while(start<end && numbers[end]==numbers[end+1]){end--;}}}}}return result;}
}
31. Partition Array:点击打开链接
例如:[3,2,2,1],k=2,Output:1
思路:“两大阵营”
根据题意分阵营,左边都是小于k的数,右边都是大于k的数
相向双指针遍历数组,如果左边遍历到的数小于k就left++,如果右边遍历到的数大于k就right--
如果不属于我方阵营就和一个不属于对方阵营的数交换位置
注意: 1.本题最后return the partitioning index,eg:the first index i nums[i] =k,因为每次left++可以保证return left的值就是题目所要求。
2.题目还要求如果所以元素都比k小,就要返回数组的长度,例如:[1,1,1,1],k=2,Output:4
这种情况就是一直left++,当left=3时,仍然满足while(left<=right && nums[left]<k),还会再left++一次,此时返回left=4
public class Solution {/** *@param nums: The integer array you should partition*@param k: As description*return: The index after partition*/public int partitionArray(int[] nums, int k) {if(nums==null || nums.length==0){return 0;}int left=0;int right=nums.length-1;while(left<=right){while(left<=right && nums[left]<k){left++;}while(left<=right && nums[right]>=k){right--;}if(left<=right){int temp=nums[left];nums[left]=nums[right];nums[right]=temp;left++;right--;}}return left;}
}
373.Partition Array by Odd and Even:点击打开链接
public class Solution {/*** @param nums: an array of integers* @return: nothing*/public void partitionArray(int[] nums) {if(nums==null || nums.length==0){return;}int left=0;int right=nums.length-1;while(left<=right){ //根据题意分两大阵营while(left<=right && nums[left]%2==1){ //奇数阵营left++;}while(left<=right && nums[right]%2==0){ //偶数阵营right--;}if(left<=right){int temp=nums[left];nums[left]=nums[right];nums[right]=temp;left++;right--;}}}
}
49. Sort Letters by Case:点击打开链接
public class Solution {/** *@param chars: The letter array you should sort by Case*@return: void*/public void sortLetters(char[] chars) {if(chars==null || chars.length==0){return;}int left=0;int right=chars.length-1;while(left<=right){ while(left<=right && chars[left]>='a' && chars[left]<='z'){ //小写字母阵营left++;}while(left<=right && chars[right]>='A' && chars[right]<='Z'){ //大写字母阵营right--;}if(left<=right){char temp=chars[left];chars[left]=chars[right];chars[right]=temp;left++;right--;}}}
}
144.Interleaving Positive and Negtive:点击打开链接
思路:与上面的两大阵营稍有不同,这题是用同向双指针,因为是正负数间隔,所以哪个符合条件哪个指针+2
但是题目没有说明原数组正,负整数的个数,因此要先判断正负数的个数情况,哪个多哪个就作为index=0
class Solution {/*** @param A: An integer array.* @return: void*/public void rerange(int[] A) {int posNum = 0, negNum = 0; for (int i = 0; i < A.length; i++) { if (A[i] > 0) { posNum++; } else { negNum++; } } int posIndex = 1, negIndex = 0; if (posNum > negNum) { posIndex = 0; negIndex = 1; } while (negIndex < A.length && posIndex < A.length) { while (negIndex < A.length && A[negIndex] < 0) { negIndex += 2; } while (posIndex < A.length && A[posIndex] > 0) { posIndex += 2; } if (posIndex < A.length && negIndex < A.length) { int tmp = A[posIndex]; A[posIndex] = A[negIndex]; A[negIndex] = tmp; posIndex += 2; negIndex += 2; } } }
}
148.Sort Colors:点击打开链接
3-way-partition问题
思路:1.由i遍历数组,leftPointer一直指向左边部分后一个数,rightPointer指向右边部分前一个数
2.如果当前nums[i]属于左边部分,nums[leftPointer]和nums[i]交换位置,使得leftPointer真正指向一个属于左边部分的数
然后leftPointer++,i++同步跟上
3.如果当前nums[i]属于中间部分,i++表示跳过,因为中间部分的元素就要留在中间
4.如果当前nums[i]属于右边部分,nums[rightPointer]和nums[i]交换位置,使得rightPointer真正指向一个属于右边部分的数
然后rightPointer--,此时,i不能同步++向后移,因为不知道被换的nums[rightPointer]是不是也属于右边部分,
所以还要从这个i位置开始看nums[i]属于哪个部分
注意:多跑几个例子就可以知道,i会比leftPointer走的快,所以即使交换后leftPointer指向的是左边阵营结束元素的下一个元素,也是i走过的元素,因此是1
rightPointer指向的是右边阵营结束元素的下一个元素,但是方rightPointer的走向是向左的
class Solution {/*** @param nums: A list of integer which is 0, 1 or 2 * @return: nothing*/public void sortColors(int[] nums) {if(nums==null || nums.length==0){return;}int leftPointer=0; int rightPointer=nums.length-1; int i=0; while(i<=rightPointer){ if(nums[i]==0){swap(nums,i,leftPointer); //是0就被交换到1阵营leftPointer++;i++;}else if(nums[i]==1){ i++; //是1就跳过}else{swap(nums,i,rightPointer); //是2就被交换到当前2阵营rightPointer--;}}}private void swap(int[] nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}
}
625.Partition Array II:点击打开链接
public class Solution {/*** @param nums an integer array* @param low an integer* @param high an integer* @return nothing*/public void partition2(int[] nums, int low, int high) {if(nums==null || nums.length==0){return;}int i=0;int leftPointer=0;int rightPointer=nums.length-1;while(i<=rightPointer){if(nums[i]<low){swap(nums,i,leftPointer);leftPointer++;i++;}else if(nums[i]>=low && nums[i]<=high){i++;}else if(nums[i]>high){swap(nums,i,rightPointer);rightPointer--;}}}private void swap(int[] nums,int i,int j){int temp=nums[i];nums[i]=nums[j];nums[j]=temp;}
}
143.Sort Colors II:点击打开链接
彩虹排序问题 : O(nlogk)
思路:先分成两分,再递归分
例如:[3,2,2,1,4],k=4
先分成colorMid=(colorFrom+colorTo)/2=(1+4/)2=2,所以开始的两分是[2,2,1,3,4],再递归分每一分[2,2,1]和[3,4]
也就是两分先有个大致顺序,再不断递归局部的顺序,直到整体完全有序。
注意:前面两个return;
class Solution {/*** @param colors: A list of integer* @param k: An integer* @return: nothing*/public void sortColors2(int[] colors, int k) {if(colors==null || colors.length<k-1){return;}rainbowSort(colors,1,k,0,colors.length-1);}private void rainbowSort(int[] nums,int colorFrom,int colorTo,int left,int right){if(colorFrom==colorTo){return;}if(left>right){return;}int colorMid=(colorFrom+colorTo)/2;int l=left,r=right;while(l<=r){while(l<=r && nums[l]<=colorMid){l++;}while(l<=r && nums[r]>colorMid){r--;}if(l<=r){int temp=nums[l];nums[l]=nums[r];nums[r]=temp;l++;r--;}}rainbowSort(nums,colorFrom,colorMid,left,r); //while(l<=r)是循环条件,所以跳出了l>r是跳出条件rainbowSort(nums,colorMid+1,colorTo,l,right); //所以下一次递归的时候一定是l>r,r在前面}
}
[Algorithm]九章七:Two Pointer相关推荐
- [Algorithm]九章九之一:Matrix DP
109. Triangle:点击打开链接 方法一:自底向上 例如:从6开始,依赖于4和1中小者,再加上本身 注意:这种三角形第n行的长度是n+1,一共有n-1行,第0行的长度为1, Time:O(n^ ...
- SQL基础教程MICK版 ···第七、八、九章总结
SQL基础教程MICK版 ···第七.八.九章总结 表的联结 -- 内联结.外联结 表的合并--- UNION (其他操作对MYSQL不适用.没有看) 关于ROLLUP---显示小计和总计 驱动的概念 ...
- ★【世龙最爱之作】☆【丑丫头变身美女校花,不恋情的人懊恼,可是有了爱情之后更烦恼】第七十九章★
丑丫头变身美女校花第七十九章 全部烧烤大餐,终极仍是以快活满意的主旋律,在一个半小时之后完善的停止了.合法大家都整理筹备散场的时候. 沈芳突然道:"要不,大家去唱歌吧?" 吴以默立 ...
- 鸟哥的Linux私房菜(服务器)- 第十九章、主机名控制者: DNS 服务器
第十九章.主机名控制者: DNS 服务器 最近更新日期:2011/08/05 我们都知道,在『记忆』的角色上,人脑总是不如计算机的,而人们对文字的印象又比数字高.因此,想要使用纯粹的 TCP/IP 来 ...
- 第十九章、主機名稱控制者: DNS 伺服器
转自:http://linux.vbird.org/linux_server/0350dns.php 第十九章.主機名稱控制者: DNS 伺服器 最近更新日期:2011/08/05 我們都知道,在『記 ...
- 中科大“九章”历史性突破,但实现真正的量子霸权还有多远?
作者 | 马超 出品 | AI科技大本营 头图 | CSDN下载自视觉中国 10月中旬,政府高层强调要充分认识推动量子科技发展的重要性和紧迫性,加强量子科技发展战略谋划和系统布局,把握大趋势,下好先手 ...
- 分治习题--九章算法培训课第三章笔记
1.Maximum Depth of Binary Tree 这是道简单的分治习题了 分: 左子树最大深度 右子树最大深度 治: 最大深度等于max(左子树,右子树)+1 public class S ...
- 最长回文子串动态规划_九章算法 | 微软面试题:最长回文子串
给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串. 在线评测地址:LintCode 领扣 样例 1: 输入:"abcdzdcab&quo ...
- 鸟哥的Linux私房菜(基础篇)- 第十九章、认识与分析登录文件
第十九章.认识与分析登录文件 最近升级日期:2009/09/14 当你的 Linux 系统出现不明原因的问题时,很多人都告诉你,你要查阅一下登录文件才能够知道系统出了什么问题了,所以说,了解登录文件是 ...
最新文章
- RK3399 Ubuntu修改任务栏为自动隐藏和修改桌面背景
- DWM1000 长距离模块讨论
- 注意,ruby循环体定义的变量在结束时后,变量还存在
- 函数--函数的快速体验
- Android Studio更新成2.3以后Gradle大坑拯救,gradle安装异常解决办法
- 小汤学编程之JavaEE学习day05——会话管理、文件上传与下载、Ajax
- 【FlexSim2019】自学笔记:一个实例看何为A连接?何为S连接?其意义的深入探讨
- MD1——2 Corner
- 5.3 Zend_Log_Filter
- RTR/SLA 在多ISP环境下下的应用--已经更新,切换后线路恢复时,已能自动恢复
- Centos7 安装字体库中文字体
- winform textbox文本框根据内容自动调整高度
- HFSS - 同轴馈电矩形微带天线设计与仿真
- 网络工程师职场进化手册
- HTML——HTML中的特殊符号
- kali翻译插件_Kali2.0上的一款翻译神器【GoldenDict神器介绍】
- 详解sigmoid与softmax, 多分类及多标签分类
- Windows 平台下局域网劫持测试工具 – EvilFoca
- 6款真正好用的播放器推荐
- 用MATLAB绘制国债NSS模型,Matlab在数字信号处理中的运用.ppt
热门文章
- SpringBoot 项目中 YML 配置文件的使用
- 公司网站如何让用户使用QQ第三方登录
- KubeCon + 欧洲云原生大会 2022,看看云原生Wasm日的演讲
- 计算机打印机提示无法打印,电脑打印提示由于打印机的当前设置有问题,Windows无法打印怎么解决...
- 安全,恐惧,社会生活,含蓄,贱化,衰老
- 卡尔曼滤波器公式推导
- SolarWinds安装、配置、使用手册
- 微信小程序图片无缝衔接(微信小程序)
- [cognexVisionPro]错误:Vpp_1.vpp包含Cognex.visionPro.ToolBlock.CogToolBloc而不是CogJob
- iphone4越狱后找不到可以安装的openssh