一、第二次写两数之和代码思想过程:
- 继续昨天写的两数之和,今天又继续与那道题作斗争。对我这种菜鸟来说真的太难了,哭泣 o(╥﹏╥)o。今天挣扎了几小时后,沉浸在BUG的海洋中,代码改了一遍又一遍后,每改完一个就期望着这是最后一个,结果每次快自救上岸,但浪花不断一次一次把我重打回BUG的海洋,就差淹死了,最后终于一个浪花拍死了我,没救了~~~~,暴风式哭泣。
- 今天写了一天的代码:
public int[] twoSum(int[] nums, int target) {
//nums中可能存在重复的元素,假如两数之和在数组中有解,
//则第一个数的下标在cu中,第二个数的下标在cut中
int[] cu=new int[100],cut=new int[100];
for(int i=0;i<nums.length;i++){
cu[nums[i]]=-1;
}
for(int i=0;i<nums.length;i++){
if(cu[nums[i]]!=-1){
cut[nums[i]]=i;
}else{
cu[nums[i]]=i;
cut[nums[i]]=i;
}
}
//先进行快排
quicksort(nums, 0, nums.length-1);
//再进行二分查找
for(int i=0;i<nums.length;i++){
int temp=dividefind(nums, target-nums[i],i, nums.length-1);
if(temp!=-1){
return new int[]{cu[nums[i]],cut[nums[temp]]};
}
}
return new int[]{-1,-1};
}
//二分查找
public int dividefind(int[] nums,int number,int l,int r) {
int mid=-1;
while(l<=r){
mid=(l+r)/2;
if(nums[mid]==number){
return mid;
}else if(nums[mid]>number){
r=mid-1;
}else{
l=mid+1;
}
}
return -1;
}
//快排
public void quicksort(int[] nums,int l,int r){
if(l<r){
int mid=findmid(nums,l,r);
quicksort(nums, l, mid-1);//左排序
quicksort(nums, mid+1, r);//右排序
}
return;
}
public int findmid(int[] nums, int l, int r) {
int mvalue=nums[l];
while(l<r){
while(l<r&&nums[r]>=mvalue){
r--;
}
nums[l]=nums[r];
while(l<r&&nums[l]<=mvalue){
l++;
}
nums[r]=nums[l];
}
nums[l]=mvalue;
return l;
}
- 我想了一个解决思路是,先用快排将数组变成有序的,但这样的话,新数组对应的下标与原数组就不相同。于是就先是定义了一个cu数组,下标为元素,值为原数组的下标,但后来出BUG,意思是假如数组中有两个同样的元素,则一个cu数组只能保留一个元素的下标。最后我就用了两个数组解决,cu和cut,这道题目的解只有一个。排好序之后用二分查找找第二个数的解。想着快排的时间复杂度是O(nlogn),二分查找的时间复杂度是O(logn),怎么也比暴力解决时间复杂度低,但最后发现自己的思想是错的,想的太复杂了。
- 快排代码一开始是按自己所理解的思想自己写了一个,但后来在边界部分老是BUG,后来改了几遍后就去网上找了一个大佬写的完美版快排,看完理解后,发现这种方法也太牛逼了吧,自己暂时没找到BUG,以后就这样写快排代码了,解决了我一直纠结的边界问题。
- 然后使用二分查找找解的第二个数,二分查找虽然简单,但自己还是改了一堆BUG,唉~~~~。
- 最后测试出了一个BUG,如果元素中有负值的话,是不可能存在cu数组中,然后想应该怎么办好,思考过后恍然大悟,cu数组的作用貌似和Map作用十分相似,我不如直接按昨天看的LeetCode官方解答写,彻底被打倒,叹息,白忙一场。。。