LC的daily真是越来越骚了,本来打算写一个O(n3)T了后再来优化,结果居然过了,虽然击败感人…
//时间击败6.58% //空间击败7.14% class Solution { public: int threeSumClosest(vector<int>& nums, int target) { int n = nums.size(); int minn = INT_MAX; int ans; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) { if(i == j || j == k || i == k) continue; int tmp = nums[i] + nums[j] + nums[k]; if(tmp == target) return tmp; if(abs(tmp - target) < minn) { minn = abs(tmp - target); ans = tmp; } } return ans; } };
这可能是我在LC上A过最低效的算法了。
那么来思考一下怎么优化吧。
上述算法低效的原因是用了三重循环依次枚举每一个数,很直观也很低效,考虑简化这个过程来获取更优的时间复杂度。
对于题述的三个数a,b,c,我们求的是sum=a+b+c与target的相似关系,即a+b+c≈target。如果我们变一下相,则有a=target-b-c,即对于每一个给定的a,所得到的的sum值仅与b和c有关,那么只需要去枚举b和c就好了。
实际实现上,采用双指针来实现。一个外部大循环用来枚举a,然后内部定义两个指针l与r,l指向a之后的第一个元素,r指向最后一个元素。通过比较当前元素和与target的大小关系来不断缩小区间,这样就可以做到同时枚举b与c两个元素。
class Solution { public: int threeSumClosest(vector<int>& nums, int target) { int n = nums.size(); sort(nums.begin(), nums.end()); int ans = nums[0] + nums[1] + nums[2]; for(int i = 0; i < n - 2; i++) { int l = i + 1, r = n - 1; while(l < r) { int tmpsum = nums[l] + nums[r] + nums[i]; if(abs(tmpsum - target) < abs(ans - target)) { ans = tmpsum; } if(tmpsum > target) r--; else if(tmpsum < target) l++; else return tmpsum; } } return ans; } };
评论
还没有任何评论,你来说两句吧!