您的位置:首页 > 其它

LintCode 解题记录 Array 17.6.5

2017-06-05 12:35 375 查看
周六做的几道题目,今天周一抽一个上午总结一下。

首先贴两张图,用来激励自己吧。





LintCode Combinations

给定两个数n和k,返回1~n中的任取k个数的所有组合。

dfs+回溯。难度一般。

vector<vector<int> > combine(int n, int k) {
// write your code here
vector<vector<int>> ret;
vector<int> tmp;
int cnt = 0;
if (n <= 0) return ret;
for (int i = 1; i <= n; i++) {
dfs(ret, tmp, cnt, i, n, k);
}
return ret;
}

void dfs(vector<vector<int>> &ret, vector<int> tmp, int cnt, int idx, int n, int k) {
cnt++;
tmp.push_back(idx);
if (cnt == k) {
ret.push_back(tmp);
return;
}
for (int i = idx+1; i <= n; i++) {
dfs(ret, tmp, cnt, i, n, k);
}
}


LintCode Continuous Subarray Sum

返回最大子序列和的beginIndex和endIndex。

思路和最大子序列和一样,用两个指针记录最大和的开始和目前的位置。

vector<int> continuousSubarraySum(vector<int>& A) {
// Write your code here
vector<int> ret(2, 0);
vector<int> tmp;
int sum = 0, ans = INT_MIN;
for (int i = 0; i < A.size(); i++) {
sum += A[i];
tmp.push_back(i);
if (sum > ans) {
ans = sum;
ret[0] = tmp[0];
ret[1] = tmp[tmp.size()-1];
}
if (sum < 0) {
sum = 0;
tmp.clear();
}
}
return ret;

}


LintCode Find Peak Element

Challenge:时间复杂度O(logn)

一看到O(logn)多半是和二分有关了。这道题可以用画图来很直观的理解。题目给的条件很有用。

贴代码:

int findPeak(vector<int> A) {
// write your code here
int left = 1, right = A.size()-2;
int mid = 0;
while (left < right) {
mid = (left+right) >> 1;
if (A[mid] < A[mid+1]) left = mid+1;
else if (A[mid] < A[mid-1]) right = mid-1;
else return mid;
}
return left;
}


LintCode Find the Duplicate Number

给定一个大小为n+1的数组,其中所有的数都在1~n之间,已知有且有一个数重复,问这个重复的数是多少。要求:1.不能改变原数组(不能用排序) 2.空间复杂度为O(1)(不能用Hash) 3.时间复杂度小于O(n^2)(不能用Brute-force)

第一种方法:1.O(nlogn) 二分搜索法

由于所有的数都是在1~n之间,那么对于数n/2,如果该数组中小于等于该数的次数大于n/2,则说明重复的数在1~n/2之间,否则就在n/2+1~n之间。所以时间复杂度是O(nlogn)。

代码:

int findDuplicate(vector<int>& nums) {
// Write your code here
int min = 1, max = nums.size()-1;
int cnt = 0;
while (min < max) {
int mid = (min+max) >> 1;
cnt = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] <= mid) cnt++;
}
if (cnt <= mid) min = mid+1;
else max = mid;
}
return min;
}


第二种方法:O(n) Robert Floyd 算法

该算法常用于判断给定链表是否有环、以及求环的起点、以及求环的长度。贴一个写的不错的博客:

Robert Floyd Algorithm

其实这个算法自己画图稍微写几个公式就能理解了,关于此算法的应用有 Linked List Cycle + Linked List CycleII(直接在LintCode里搜索就能找到这两题)

那么本题用了这样的一个映射:index -> val。由于有重复的元素那么一定存在index1 != index2 但是 val1 == val2。那么x_n = f(x_n-1)按照这样的关系顺下去,最终环的起点就是要找的重复值。

代码:

int findDuplicate(vector<int>& nums) {
// Write your code here
int slow, fast, t;
slow = fast = t = 0;
while (true) {
slow = nums[slow];
fast = nums[nums[fast]];
if (slow == fast) break;
}
while (true) {
slow = nums[slow];
t = nums[t];
if (slow == t) break;
}
return slow;
}


总结:

1.温故而知新,尝回来看看,看看做过的题,在思考提升一下。

2.掌握 Robert Floyd判断环的方法,重要,面试常考。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: