Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
思路:
假设把A[i]之前的连续段叫做sum。A[i]是以i结尾的连续子数组的最大和。可以很容易想到:
1. 如果sum>=0,就可以和A[i]拼接在一起构成新的sum'。因为不管A[i]多大,加上一个正数总会更大,这样形成一个新的candidate。
2. 反之,如果sum<0,就没必要和A[I]拼接在一起了。因为不管A[i]多小,加上一个负数总会更小。此时由于题目要求数组连续,所以没法保留原sum,所以只能让sum等于从A[i]开始的新的一段数了,这一段数字形成新的candidate。
3. 将每次得到新的candidate都和全局的result进行比较,那么必然能找到最终答案。
在循环过程中,用result记录历史最大的值。从A[0]到A[n-1]一步一步地进行。
//经典代码Kadane's algorithm
//时间复杂度显然是O(N),因为数组只被扫描了一遍。
bool g_InvalidInput = false;//设置全局变量来区分 1.子数组和的最大值是0 还是 2.无效输入 这两种情况
int maxSubArray(int *data, int n) {
if(data == NULL || n <= 0) {
g_InvalidInput = true;
return 0;
}
int currSum = 0; //或者初始化为 currSumm = INT_MIN 也OK。
int result = 0x800000000; //这里一定要赋值result = 0x800000000否则遇到全部为负数的数组将出错。
for(int i = 0; i < n; ++i){
if(currSum >= 0)
currSum += data[i];
else
currSum = data[i];
if(currSum > result){
result = currSum;
}
}
return result;
}
vector<int> maxSubArray(int *data, int n) {
int sum = 0; //或者初始化为 summ = INT_MIN 也OK。
int result = INT_MIN; //这里一定要赋值result=INT_MIN否则遇到全部为负数的数组将出错。
int start = 0;
int end = 0;
vector<int> res_index;
for(int i = 0; i < n; ++i){
if(sum >= 0)
sum += data[i];
else {
sum = data[i];
start = i;
}
if(sum > result){
result = sum;
end = i;
}
}
res_index.push_back(start);
res_index.push_back(end);
return res_index;
}
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4]
,
the contiguous subarray [2,3]
has the largest product = 6
.
class Solution {
public:
int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
int currMax, currMin, result;
currMax = currMin = result = nums[0];
for(int i = 1; i < n; ++i) {
int tmpMax = currMax * nums[i];
int tmpMin = currMin * nums[i];
//如果不用tmpmax,而是写currMax *= nums[i],那么运行完此行,会对下一行结果有影响
currMax = max(nums[i], max(tmpMax, tmpMin));
currMin = min(nums[i], min(tmpMax, tmpMin));
result = max(result, currMax);
}
return result;
}
};
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
题意翻译:其实就是在所给数组里面找一个子数组,子数组里的每一个元素都不能相邻,然后求其最大和。class Solution {
public:
int rob(vector<int>& nums) {
int len = nums.size();
if(len == 0)
return 0;
if(len == 1)
return nums[0];
vector<int> dp(len, 0);
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
for(int i = 2; i < len; ++i) {
dp[i] = max(dp[i - 1], dp[i- 2] + nums[i]);
}
return dp[len - 1];
}
};
int rob(vector<int>& nums) {
int take = 0;
int dontTake = 0;
int maxProfit = 0;
for(int i = 0 ; i < nums.size(); ++i){
take = nonTake + nums[i];
dontTake = maxProfit;
maxProfit = max(take, dontTake);
}
return maxProfit;
}
After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
题意:House Robber的题中,首尾也算作相邻。求最大和。class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
if(n == 1) return nums[0];
int take = 0, dontTake = 0, profit1 = 0, profit2 = 0;
for(int i = 0; i < n - 1; ++i) {
take = dontTake + nums[i];
dontTake = profit1;
profit1 = max(take, dontTake);
}
take = 0, dontTake = 0;
for(int i = 1; i < n; ++i) {
take = dontTake + nums[i];
dontTake = profit2;
profit2 = max(take, dontTake);
}
return max(profit1, profit2);
}
};