273 Integer to English Words
/*
My thoughts
1. 写一个专门处理三个数字的函数,注意应对001等Leading zeros的问题
2. 空格的处理:当要写入ans时,若ans.size()!=0,加空格后再写入
3. 注意单词不要拼写错误
4. 有负数
*/
class Solution {
public:
vector<string> Words;
vector<string> conj;
Solution()
{
Words.resize(105);
conj.resize(5);
conj[1]="";
conj[2]="Thousand";
conj[3]="Million";
conj[4]="Billion";
Words[0]="Zero";
Words[1]="One";
Words[2]="Two";
Words[3]="Three";
Words[4]="Four";
Words[5]="Five";
Words[6]="Six";
Words[7]="Seven";
Words[8]="Eight";
Words[9]="Nine";
Words[10]="Ten";
Words[11]="Eleven";
Words[12]="Twelve";
Words[13]="Thirteen";
Words[14]="Fourteen";
Words[15]="Fifteen";
Words[16]="Sixteen";
Words[17]="Seventeen";
Words[18]="Eighteen";
Words[19]="Nineteen";
Words[20]="Twenty";
Words[30]="Thirty";
Words[40]="Forty";
Words[50]="Fifty";
Words[60]="Sixty";
Words[70]="Seventy";
Words[80]="Eighty";
Words[90]="Ninety";
Words[100]="Hundred";
}
string intTostr(int num)
{
stringstream ss;
ss<<num;
string ans = ss.str();
return ans;
}
string Three(string num)
{
string ans = "";
int n = atoi(num.c_str());
if (n>=100 && n<=999)
{
if (n%100==0)
{
ans = Words[num[0]-'0']+" "+Words[100];
return ans;
}
ans = Words[n/100]+" "+Words[100]+" ";
n=n-n/100*100;
}
if(n<=20 || n%10==0)
{
ans+=Words[n]; return ans;
}
ans+=Words[n/10*10]+" "+Words[n%10];
return ans;
}
string numberToWords(int num)
{
string ans ="";
if (num<0) ans="Negative ";
string number = intTostr(num);
int len = number.size();
int cutLen = len - len/3*3;
len = len /3;
if (cutLen!=0) len++; else cutLen = 3;
for(int i=len;i>=1;i--)
{
string tmpNum = number.substr(0,cutLen);
if (tmpNum=="000")
{
if (i!=1)
{
number=number.substr(cutLen);
}
cutLen = 3;
continue;
}
if (ans.size()!=0) ans+=" ";
ans += Three(tmpNum);
if (i!=1)
{
ans+=" "+conj[i];
number=number.substr(cutLen);
}
cutLen = 3;
}
return ans;
}
};
// ------------------WA cases-------------
/*
WA reason: ninety拼写错误
Input:
1234567891
Output:
"One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninty One"
Expected:
"One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One"
WA reason: 忘记处理所有的000项目
Input:
1000
Output:
"One Thousand Zero Hundred"
Expected:
"One Thousand"
WA:没有处理leading zeros
Input:
1001
Output:
"One Thousand Zero Hundred One"
Expected:
"One Thousand One"
*/
233 Number of Digit One
// --------------------Seeing Discuss-------------
/*
url:
https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python
Go through the digit positions by using position multiplier m with values 1, 10, 100, 1000, etc.
For each position, split the decimal representation into two parts, for example
split n=3141592 into a=31415 and b=92 when we're at m=100 for analyzing the hundreds-digit.
And then we know that the hundreds-digit of n is 1 for prefixes "" to "3141", i.e., 3142 times.
Each of those times is a streak, though. Because it's the hundreds-digit, each streak is 100 long.
So (a / 10 + 1) * 100 times, the hundreds-digit is 1.
Consider the thousands-digit, i.e., when m=1000. Then a=3141 and b=592. The thousands-digit
is 1 for prefixes "" to "314", so 315 times. And each time is a streak of 1000 numbers. However,
since the thousands-digit is a 1, the very last streak isn't 1000 numbers but only 593 numbers,
for the suffixes "000" to "592". So (a / 10 * 1000) + (b + 1) times, the thousands-digit is 1.
The case distincton between the current digit/position being 0, 1 and >=2 can easily be done
in one expression. With (a + 8) / 10 you get the number of full streaks, and a % 10 == 1 tells
you whether to add a partial streak.
*/
class Solution {
public:
int countDigitOne(int n)
{
int ones = 0;
for(long long m = 1;m<=n;m*=10)
{
int a = n/m, b= n%m;
ones += (a+8)/10*m +(a%10==1)*(b+1);
}
return ones;
}
};
174 Dungeon Game
// ---------------------Seeing Discuss--------------
/*
URL:
https://discuss.leetcode.com/topic/6912/c-dp-solution
Use hp[i][j] to store the min hp needed at position (i, j), then do the calculation
from right-bottom to left-up.
Note: adding dummy row and column would make the code cleaner.
Discuss hp[i][j]表示的是,(i,j)位置需要的最少血量;
然后倒着循环;
并且在计算hp[i][j]时,如果>0 则1,小于0,则血量
小结:
这种方格dp,算不出来要想着倒着来,或者换个状态!
*/
class Solution {
public:
int calculateMinimumHP(vector<vector<int> >& dungeon)
{
int M = dungeon.size();
int N = dungeon[0].size();
vector< vector<int> >hp(M+1,vector<int>(N+1,INT_MAX));
hp[M][N-1] = 1;
hp[M-1][N] = 1;
for(int i=M-1;i>=0;i--)
{
for(int j=N-1;j>=0;j--)
{
int need = min(hp[i+1][j],hp[i][j+1]) - dungeon[i][j];
hp[i][j]=need<=0? 1:need;
}
}
return hp[0][0];
}
};
// ---------------------WA---------------
/* 35 / 44 test cases passed.
WA data point
Input:
[[1,-3,3],[0,-2,0],[-3,-3,-3]]
Output:
5
Expected:
3
找不到最x生命值和当前生命值的平衡。。。
class Solution {
public:
int calculateMinimumHP(vector<vector<int> >& dungeon)
{
int row = dungeon.size();
if (row==0) return 0;
int col = dungeon[0].size();
vector<vector<int> > f(row+1,vector<int> (col+1,0));
vector<vector<int> > g(row+1,vector<int> (col+1,0));
f[0][0]=dungeon[0][0];
g[0][0]=dungeon[0][0];
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
if (i==0 && j==0) continue;
int gTmpUp = INT_MIN, gTmpLeft = INT_MIN;
int fTmpUp=0, fTmpLeft=0;
if (i-1>=0)
{
fTmpUp = dungeon[i][j]+f[i-1][j];
gTmpUp = min(g[i-1][j],fTmpUp);
}
if (j-1>=0)
{
fTmpLeft = dungeon[i][j]+f[i][j-1];
gTmpLeft = min(g[i][j-1],fTmpLeft);
}
if(gTmpUp > gTmpLeft)
{
f[i][j]=fTmpUp;
g[i][j]=gTmpUp;
}
else
{
f[i][j]=fTmpLeft;
g[i][j]=gTmpLeft;
}
}
}
if (g[row-1][col-1]>0) return 1;
return abs(g[row-1][col-1])+1;
}
};
*/
149 Max Points on a Line
// --------------Seeing Discuss---------------
/*
Url:
https://discuss.leetcode.com/topic/6028/sharing-my-simple-solution-with-explanation/2
Discuss大致思想:
1. 对于每个点p,计算他和其他所有点的斜率,并用map统计每个斜率出现的次数;
2. 其中对于与p横纵坐标相同的点,用samePoint来累计
3. 横坐标与p同的,map放在INT_MAX里记录
4. 每个点算完以后,知道斜率出现次数最多的localmax,来更新全局max
5. 因为已经定了点p的位置,也就是这条直线必经过点p,所以,截距也是定的,只需要计算斜率就行了。
要点:
选定了点p,只计算斜率即可,因为必定过点p,截距也是定的。
*/
class Solution {
public:
int maxPoints(vector<Point>& points)
{
int result = 0;
for(int i=0;i<points.size();i++)
{
int samePoint = 1;
unordered_map<double,int> mapping;
mapping[INT_MAX]=0;
for(int j=i+1;j<points.size();j++)
{
if (points[i].x==points[j].x && points[i].y==points[j].y)
samePoint++;
else
if (points[i].x==points[j].x)mapping[INT_MAX]++;
else
{
double slope = double(points[i].y-points[j].y)/double(points[i].x-points[j].x);
if (mapping.find(slope)==mapping.end())
mapping[slope]=1;
else mapping[slope]++;
}
}
int localMax = 0;
for(auto it = mapping.begin();it!=mapping.end();it++)
{
localMax=max(localMax,it->second);
}
localMax += samePoint;
result = max(result,localMax);
}
return result;
}
};
/*
My Thoughts:
1. 找到最多的点,使得他们在一条直线上
2. 先给所有的点,按照x坐标从小到大排序
3. 两点确定一条直线,斜率,截距可以知道。
4. 判断其他的点是不是(斜率,截距)组的点即可
5. 注意跟横纵坐标平行的直线
*/
146 LRU Cache
class LRUCache{
public:
LRUCache(int capacity)
{
cache.clear();
ranking.clear();
cap = capacity;
pri = 0;
}
int get(int key)
{
if (cache.find(key)!=cache.end())
{
map<int,int>::iterator it = ranking.find(cache[key].first);
ranking.erase(it);
pri++;
cache[key].first = pri;
ranking[pri]=key;
return cache[key].second;
}
return -1;
}
void set(int key, int value)
{
if (cache.find(key)==cache.end() && cache.size()==cap)
{
map<int,int>::iterator it = ranking.begin();
cache.erase(it->second);
ranking.erase(it);
}
if(cache.find(key)!=cache.end())
{
map<int,int>::iterator it = ranking.find(cache[key].first);
ranking.erase(it);
}
pri++;
pair<int,int> x(pri,value);
cache[key]=x;
ranking[pri]=key;
return ;
}
private:
map<int,pair<int,int> > cache;// first: the pri; second: the value
map<int,int> ranking; // ranking[pri]= key;
int pri;
int cap;
};