LeetCode 2016 273,233,174,149,146

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;
};




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值