连续子数组最大和
动态规划的题目,定义dp(i)
是以第i个数字结尾的子数组的最大和,那么有如下动态规划方程:
dp(i)=num(i),i=0或者dp(i−1)<=0
dp(i)=dp(i−1)+num(i),i>0且dp(i−1)>0
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
if (array.size() == 0)
return 0;
vector<int>dp(array.size());
int cur = numeric_limits<int>::min();
for (int i = 0; i < array.size(); ++i)
{
if (i == 0 || dp[i-1] <= 0)
dp[i] = array[i];
if (i>0 && dp[i-1] > 0)
dp[i] = dp[i - 1] + array[i];
if (dp[i] > cur)
cur = dp[i];
}
return cur;
}
};
当然也可以用局部最优和全局最优的方式来做,局部最优保证以当前数字结尾,的最大值那么有:
local(i)=max(local(i−1)+num(i),num(i))
然后求全局最优:
global(i)=max(local(i),global(i−1))
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
vector<int>a;
a.swap(array);
vector<int>local(a.size());
vector<int>global(a.size());
local[0] = a[0];
global[0] = a[0];
for (int i = 1; i<a.size(); ++i)
{
local[i] = max(a[i], local[i - 1] + a[i]);
global[i] = max(local[i], global[i - 1]);
}
return global[a.size() - 1];
}
};
从1到n整数中1出现的次数
剑指offer上面讲的不清楚。
参考:http://blog.youkuaiyun.com/yi_afly/article/details/52012593
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
if (n < 0)
return 0;
int count = 0;
int weight = 0;
int round = 0;
int base = 1;
int origin = n;
while (n > 0)
{
weight = n % 10;
round = n / 10;
if (weight == 1)
{
count += round*base;
count += ((origin%base) + 1);
}
else if (weight == 0)
{
count += round*base;
}
else
{
count += round*base;
count += base;
}
base *= 10;
n /= 10;
}
return count;
}
};
把数组排成最小的数
希望较高位出现较小的数,需要找到一个合适的排序规则,能够在这些全排列里面筛选出最小的数。直接排序肯定是不行的,比如12,333,9
直接排序后9出现在最高位,是不符合要求的。
给出两个数字a和b需要判断哪个数在前面就要比较ab和ba
整型的拼接先转成string,然后再比较a+b和b+a
的大小
把上述规则写成比较函数,利用sort很容易:
class comp{
public:
bool operator()(string a, string b)
{
return a + b < b + a;
}
};
class Solution {
public:
string PrintMinNumber(vector<int> numbers) {
if (numbers.size() == 0)
return string();
vector<string>n;
n.reserve(numbers.size());
for(auto num : numbers)
{
n.push_back(to_string(num));
}
sort(n.begin(), n.end(), comp());
string r;
for (auto i : n)
{
r += i;
}
return r;
}
};
丑数
2、3、5为因数,可以写一个判断丑数的代码:
int judgeUgly(int n)
{
while (n % 2==0)
n /= 2;
while (n % 3 == 0)
n /= 3;
while (n % 5 == 0)
n /= 5;
return (n == 1) ? true : false;
}
然后利用这个函数,统计n个丑数,这个办法效率较低原因在于每个数字都要进行判断一遍:
class Solution {
private:
bool judgeUgly(int n)
{
while (n % 2==0)
n /= 2;
while (n % 3 == 0)
n /= 3;
while (n % 5 == 0)
n /= 5;
return (n == 1) ? true : false;
}
public:
int GetUglyNumber_Solution(int index) {
int i = 1;
int count = 0;
while (true)
{
if (judgeUgly(i))
{
++count;
}
if (count == index)
break;
++i;
}
return i;
}
};
最终超时。
效率更高的办法叫做筛选法:
首先需要一个容器,假定里面就是存放所有1-Index的丑数,第一个个丑数是1,后面所有的丑数都是前面的丑数乘上2、3、5得来的。
class Solution {
public:
int GetUglyNumber_Solution(int index) {
vector<int>ugly(index);
ugly[0] = 1;
int i, j, k;
i = j = k = 0;
for (int count = 1; count < index; ++count)
{
ugly[count] = min(ugly[i] * 2, min(ugly[j] * 3, ugly[k] * 5));
if (ugly[count] == ugly[i] * 2)++i;
if (ugly[count] == ugly[j] * 3)++j;
if (ugly[count] == ugly[k] * 5)++k;
}
return ugly[index - 1];
}
};
第一个只出现一次的字符
hash是最简单的解法了:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
unordered_map<char,int>m;
for(int i=0;i<str.size();++i){
++m[str[i]];
}
for(int i=0;i<str.size();++i){
if(m[str[i]]==1){
return i;
}
}
return -1;
}
};