求最大子数组和
https://leetcode.com/problems/maximum-subarray/
数组表示为nums[0,1,....]
dp[i]表示从开始到第i个位置的最大子数组和
那么dp[i] = nums[i] + max(0, dp[i-1])
此时的dp[i]表示的是必须要以第i这个位置为结尾的子数组的最大和。
因此全局最大取dp[0,1,....]中最大的即可。
我们发现dp[i]只与dp[i-1]有关,为了节约存储空间,我们可以使用循环数组的概念!
class Solution {
public:
int maxSubArray(vector& nums) {
int len = nums.size();
int cur = nums[0], ret = nums[0];
for (int i = 1; i < len; i++) {
cur = nums[i] + max(0, cur);
ret = max(cur, ret);
}
return ret;
}
};
爬楼梯
一次可以上1或2层阶梯,问上到第n层有多少种上法。
https://leetcode.com/problems/climbing-stairs/
第1层有1种上法,第2层有两种上法(2、1->2)
dp[i] (i>=3)表示到第i层的上法总数,那么只有从i-1、i-2两种上去的方法。
于是有dp[i] = dp[i-1] + dp[i-2]
我们发现dp[i]只与dp[i-1]、dp[i-2]有关,为了节约存储空间,我们又可以使用循环数组的概念!
其实本题也是经典的斐波那契额数列【今天的汤=昨天的汤+前天的汤。。】
class Solution {
public:
int climbStairs(int n) {
// 循环数组的概念
vector dp;
dp.push_back(1);
dp.push_back(2);
for(int i = 3; i <= n; i++) {
dp[1 - i&1] += dp[i&1];
}
return dp[1 - n&1];
}
};
在一个无序数组中,寻找第K大的元素
https://leetcode.com/problems/kth-largest-element-in-an-array/
最朴素的方法是先将数组排序后,取相应位置的元素。【耗时、且改变了数组的位置】
构建最大堆,每次将堆顶弹出,第K次即为第K大元素。【需要写构建堆、调整堆的代码】
有个简单的思路是使用快速排序中,选取枢轴的概念。使用枢轴进行划分,则知道第K大的元素在哪一半。
class Solution {
public:
// 快排选枢轴思想
int findKthLargestHelper(vector& nums, int l, int r, int k) {
if(l < r) {
int i = l, j = r, x = nums[i];
while(i < j) {
while(i < j && x <= nums[j]) {
j--;
}
if(i < j) {
nums[i++] = nums[j];
}
while(i < j && nums[i] < x) {
i++;
}
if(i < j) {
nums[j--] = nums[i];
}
}
nums[i] = x;
if (i == k) {
return x;
}
if (i < k) {
return findKthLargestHelper(nums, i + 1, r, k);
}
if (i > k) {
return findKthLargestHelper(nums, l, i - 1, k);
}
}
return nums[l];
}
int findKthLargest(vector& nums, int k) {
int len = nums.size();
return findKthLargestHelper(nums, 0, len - 1, len - k);
}
};