LintCode 解體記錄 17.9.26
最近忙於上課、健身,也不願抽出時間來做題了。。是懶了許多。
LintCode Add Digits
題目描述
給定一個非負的整數,重複地把該數所有位上的數字加起來,直到只有一個數字。
挑戰
Could you do it without any loop/recursion in O(1) runtime?
思路
利用模10除10求得整數上的每一位之後,相加,迴圈處理直到得到的數小於10.
至於挑戰的思路,是看網上別人寫的,意思就是你從1開始列舉一下最後的結果,發現是1-9為一迴圈,即當n不能整除9時答案就是n,能整除9時答案就是9。綜合一下可以寫成(n-1)%9 + 1。
程式碼
貼一個自己寫的第一種方法。
int addDigits(int num) {
// write your code here
while (num >= 10) {
int tmp = 0;
while (num) {
tmp += num % 10;
num /= 10;
}
num = tmp;
}
return num;
}
LintCode Trailling Zeros
題目描述
計算n的階乘的末尾0的個數,n的取值範圍為long long。
挑戰
O(log N) time
思路
由於n的階乘是一個非常大非常大的數,所以先把n的階乘計算出來肯定是不現實的。發現計算末尾0的個數就是計算能整除幾個10,又因為10=2x5,且顯然階乘因子中2的出現頻率是肯定比5要高的多的,所以就是所如果能整除5,那麼他就一定能整除10。比如n=29,那麼發現它的階乘因子裡是5的倍數的有5,10,15,20,25有5個。由於要考慮類似25這樣的有多個5的因子,所以把n/5,得n=5,這裡5的倍數的因子只有一個5,所以一共有6個5的倍數因子,即末尾有6個0。
程式碼
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
long long res = 0;
while (n) {
res += n/5;
n /= 5;
}
return res;
}
LintCode Perfect Squares
題目描述
給定一個正數n,可以把它寫成k個完全平方數的和,求最小的k。
思路
可以找到最大的一個完全平方數是sqrt(n)。因此就可以從這個上界開始向下找,找出所有可能的答案中的最小值。
注意
剛開始的dfs發現超時了,加一個剪枝條件,即若發現當前的次數已經比之前得到的答案要大了,那麼就直接放棄接下來的查詢。
程式碼
int numSquares(int n) {
// write your code here
int cnt = 0, res = INT_MAX;
helper(n, cnt, res);
return res;
}
void helper(int n, int cnt, int &res) {
if (n < 4) {
res = min(res, cnt+n);
return;
}
int upperBound = sqrt(n);
for (int i = upperBound; i >= 1; i--) {
if (cnt+1 >= res) break;
helper(n-i*i, cnt+1, res);
}
}
LintCode Pow(x, n)
題目描述
計算pow(x, n)
挑戰
O(logn) time
思路
你直接返回一個pow(x, n)就AC了。。
其實這裡考察了分治思想,比如我要計算2^32次方,如果每一次乘以一個2這樣來算顯然是需要32次,即O(n)的時間複雜度;如果運用分治的思想,即2^32 = 2^16 * 2^16, 2^16 = 2^8 * 2^8,這樣的時間複雜度顯然就是O(logn)了。
注意
注意這裡的n可以為負數。
程式碼
double myPow(double x, int n) {
// Write your code here
if (n == -1) return 1/x;
if (n == 1) return x;
if (n == 0) return 1;
int e = n >> 1;
double res1 = myPow(x, e);
double res2 = myPow(x, n-2*e);
return res1 * res1 * res2;
}
LintCode Add Two Numbers
題目描述
有兩個連結串列表示兩個整數,其中數字的順序是倒序的,即最高位的數字在連結串列的最低位,現在讓你把這兩個整數加起來,然後按照上述的表示方式返回表示這個和的連結串列。
思路
簡單粗暴,直接遍歷這兩個連結串列,每一位相加,把結果存在一個容器裡,最後在利用尾插法建立一個新的連結串列返回即可。
程式碼
ListNode * addLists(ListNode * l1, ListNode * l2) {
// write your code here
vector<int> v;
int c = 0;
ListNode *p1 = l1, *p2 = l2;
while (p1 && p2) {
int n = p1->val + p2->val + c;
v.push_back(n % 10);
c = n / 10;
p1 = p1->next;
p2 = p2->next;
}
while (p1) {
int n = p1->val + c;
v.push_back(n % 10);
c = n / 10;
p1 = p1->next;
}
while (p2) {
int n = p2->val + c;
v.push_back(n % 10);
c = n / 10;
p2 = p2->next;
}
if (c) v.push_back(c);
ListNode *head = new ListNode(0);
ListNode *tail = head;
for (auto n: v) {
ListNode *p = new ListNode(n);
tail->next = p;
tail = p;
}
return head->next;
}
LintCode Add Two Numbers II
題目描述
類似於Add Two Numbers,只不過這裡數字是按正常順序存放的。
思路
先遍歷一遍把連結串列所代表的數用string存起來,然後將兩個string相加,最後建立新的連結串列。
程式碼
ListNode * addLists2(ListNode * l1, ListNode * l2) {
// write your code here
string num1 = "", num2 = "";
ListNode *p1 = l1, *p2 = l2;
while (p1) {
num1 += p1->val + '0';
p1 = p1->next;
}
while (p2) {
num2 += p2->val + '0';
p2 = p2->next;
}
string num = AddTwoString(num1, num2);
ListNode *head = new ListNode(0);
ListNode *tail = head;
for (auto c: num) {
ListNode *p = new ListNode(c-'0');
tail->next = p;
tail = p;
}
return head->next;
}
string AddTwoString(string num1, string num2) {
string ret = "";
if (num1.size() > num2.size()) swap(num1, num2);
int i = 0;
int c = 0;
for (; i < num1.size(); i++) {
int n = num1[num1.size()-1-i]-'0' + num2[num2.size()-1-i]-'0' + c;
ret += n % 10 + '0';
c = n / 10;
}
for (; i < num2.size(); i++) {
int n = num2[num2.size()-1-i] - '0' + c;
ret += n % 10 + '0';
c = n / 10;
}
if (c) ret += c + '0';
reverse(ret.begin(), ret.end());
return ret;
}
補充
當然這題的解法有很多,比如先遍歷一遍連結串列,把數字壓入堆疊,然後彈棧處理的,也有直接反轉單鏈表變成上一題的等等等。。
LintCode Split String
題目描述
給定一個字串,你可以每一個或者每兩個進行分割,返回所有可能的結果
思路
dfs搜尋+回溯。
程式碼
vector<vector<string>> splitString(string& s) {
// write your code here
vector<vector<string>> res;
vector<string> tmp;
dfs(s, 0, tmp, res);
return res;
}
void dfs(string& s, int idx, vector<string> tmp, vector<vector<string>> &res) {
if (idx >= s.size()) {
if (idx == s.size()) res.push_back(tmp);
return;
}
for (int i = 1; i <= 2; i++) {
tmp.push_back(s.substr(idx, i));
dfs(s, idx+i, tmp, res);
tmp.pop_back();
}
}
LintCode Find the Missing NumberII
題目描述
給定一個字串,其由1-n內的所有數隨機組合,但是其中少一個數,請找出這個數。
思路
dfs搜尋加回溯。首先利用等差數列求和公式求得所有的和,然後每當搜尋到一個數時就減掉該數,最後剩下的就是該數。
注意
有可能出現最後還剩兩個數,那麼此時就顯然不是答案,所以終止條件時要判斷該數是否出現過。
程式碼
int findMissing2(int n, string &str) {
// write your code here
vector<int> hash(31, 0);
int sum = (1+n) * n / 2;
int res = 0;
dfs(hash, sum, n, str, 0, res);
return res;
}
void dfs(vector<int> hash, int sum, int n, string &str, int idx, int &res) {
if (idx >= str.size()) {
if (idx == str.size() && hash[sum] == 0) res = sum;
return;
}
for (int i = 1; i <= 2; i++) {
int num = atoi(str.substr(idx, i).c_str());
if (str[idx] == '0' || num > n) break;
if (hash[num] == 1) continue;
sum -= num;
hash[num] = 1;
dfs(hash, sum, n, str, idx+i, res);
sum += num;
hash[num] = 0;
}
}
LintCode Palindrome Partitioning
題目描述
給定一個字串,將其分割成若干子字串且這些子字串都是迴文串。返回所有可能的答案。
思路
dfs+回溯。
程式碼
bool isPalindrome(string s) {
string tmp = s;
reverse(tmp.begin(), tmp.end());
return s == tmp;
}
vector<vector<string>> partition(string &s) {
// write your code here
vector<vector<string>> res;
vector<string> tmp;
dfs(res, tmp, 0, s);
return res;
}
void dfs(vector<vector<string>> &res, vector<string> tmp, int idx, string s) {
if (idx == s.size()) {
res.push_back(tmp);
return;
}
for (int i = idx; i < s.size(); i++) {
string str = s.substr(idx, i-idx+1);
if (isPalindrome(str)) {
tmp.push_back(str);
dfs(res, tmp, i+1, s);
tmp.pop_back();
}
}
}
LintCode Word BreakIII
題目描述
給定一個字串s,和一個字典dict,將s分割成若干子字串,這些子字串都在字典中,返回所有可能的結果的個數。
思路
dfs+回溯
注意
如何遍歷set,set的遍歷利用迭代器和vector形式上好像是一樣的,和map不一樣,雖然set和map同屬關聯容器。
給定dict可以先遍歷一遍求其單詞的maxLen,然後用這個manLen去剪枝後面的dfs。
程式碼
int wordBreak3(string& s, unordered_set<string>& dict) {
// Write your code here
int res = 0;
int maxLen = 0;
for (auto str: dict) {
maxLen = max(maxLen, (int)str.size());
}
dfs(s, dict, res, 0, maxLen);
return res;
}
void dfs(string &s, unordered_set<string>& dict, int &res, int idx, int maxLen) {
if (idx == s.size()) {
res++;
return;
}
for (int i = idx; i < s.size(); i++) {
string word = s.substr(idx, i-idx+1);
if (word.size() > maxLen) break;
if (dict.find(word) != dict.end()) {
dfs(s, dict, res, i+1, maxLen);
}
}
}
LintCode Expression Expand
題目描述
直接看幾個例子比較直接:
s = abc3[a] return abcaaa
s = 3[abc] return abcabcabc
s = 4[ac]dy, return acacacacdy
s = 3[2[ad]3[pf]]xyz, return adadpfpfpfadadpfpfpfadadpfpfpfxyz
思路
第一眼看到這種,秒想到了堆疊。然後就用堆疊來做。一個為數字棧,一個為字串棧。遍歷到右括號時開始進行處理。
注意
num可能為多位數。
程式碼
string expressionExpand(string &s) {
// write your code here
string res = "";
stack<char> alpha;
stack<int> num;
int i = 0;
while (i < s.size()) {
int cnt = 0;
bool digit = false;
while (isdigit(s[i])) {
digit = true;
cnt = 10*cnt + s[i]-'0';
i++;
}
if (digit) num.push(cnt); //避免壓入不存在的數字0.
if (isalpha(s[i]) || s[i] == '[') {
alpha.push(s[i]);
i++;
} else if (s[i] == ']') {
string tmp = "";
while (alpha.top() != '[') {
tmp += alpha.top();
alpha.pop();
}
alpha.pop();
reverse(tmp.begin(), tmp.end()); //首先把棧裡的字串全部彈出來,直到遇見左括號
int c = num.top(); num.pop();
string temp = "";
while (c--) {
temp += tmp;
} //然後從數字棧彈出一個數,把這個字串重複好多次。
for (auto c: temp) alpha.push(c);//最後把這個新的字串再次壓入字串棧中。
i++;
}
}
while (!alpha.empty()) {
res += alpha.top();
alpha.pop();
}
reverse(res.begin(), res.end());
return res;
}
LintCode Word Search
題目描述
給定一個字串矩陣,從裡面找出給定單詞,可以橫著組,豎著組都可以。
思路
經典DFS。時間複雜度的話額不是很懂。。
程式碼
bool exist(vector<vector<char>> &board, string &word) {
// write your code here
if (board.size() == 0 || board[0].size() == 0) return false;
int m = board.size(), n = board[0].size();
vector<vector<int>> vis(m, vector<int>(n, 0));
bool res = false;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == word[0]) {
dfs(board, i, j, word, 1, vis, m, n, res);
}
if (res) return res;
}
}
return res;
}
void dfs(vector<vector<char>> &board, int x, int y, string &word, int idx,
vector<vector<int>> vis, int m, int n, bool &find) {
if (idx == word.size()) {
find = true;
return;
}
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
//end
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
if (vis[nx][ny] == 1) continue;
vis[nx][ny] = 1;
if (board[nx][ny] == word[idx]) {
dfs(board, nx, ny, word, idx+1, vis, m, n, find);
}
if (find) return;
vis[nx][ny] = 0;
}
}
LintCode Word BreakII
題目描述
給一字串s和單詞的字典dict,在字串中增加空格來構建一個句子,並且所有單詞都來自字典。
返回所有有可能的句子。
思路
還是dfs+回溯,只是細節地方上要進行處理。另外這個方法是無法AC的,因為有一個測試用例卡住了,需要先用Word Break的方法判斷一下能否進行word Break,然後再呼叫本題的dfs。
程式碼
vector<string> wordBreak(string &s, unordered_set<string> &wordDict) {
// write your code here
vector<string> res;
if (!isWordBreak(s, wordDict)) return res;
string tmp = "";
int maxLen = 0;
for (auto str : wordDict) {
if (str.size() > maxLen)
maxLen = str.size();
}
dfs(s, wordDict, res, 0, tmp, maxLen);
return res;
}
void dfs(string &s, unordered_set<string> &wordDict, vector<string> &res,
int idx, string tmp, int maxLen) {
if (idx == s.size()) {
res.push_back(tmp);
return;
}
for (int i = idx; i < s.size() && i-idx+1 <= maxLen; i++) {
string word = s.substr(idx, i-idx+1);
if (wordDict.find(word) == wordDict.end()) continue;
string origin = tmp;
tmp += (i+1) == s.size() ? word : word + " ";
dfs(s, wordDict, res, i+1, tmp, maxLen);
tmp = origin;
}
}
int isWordBreak(string &s, unordered_set<string> &wordDict) {
int n = s.size();
vector<int> dp(n+1, 0);
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = i-1; j >= 0; j--) {
if (dp[j] && wordDict.find(s.substr(j, i-j)) != wordDict.end()) {
dp[i] = 1;
break;
}
}
}
return dp[n];
}
相關推薦
LintCode 解體記錄 17.9.26
最近忙於上課、健身,也不願抽出時間來做題了。。是懶了許多。 LintCode Add Digits 題目描述 給定一個非負的整數,重複地把該數所有位上的數字加起來,直到只有一個數字。 挑戰 Could you do it without any
LintCode 解題記錄 17.5.15 (tag: 雜湊表)
LintCode Flatten Nested List Iterator 把一個List壓平,首先想到了Spark裡的flattenMap函式- -。 兩種思路,遞迴與非遞迴。遞迴就不說了,非遞迴的就用棧來實現。為什麼要用棧呢?比如我當前遍歷到一個元素仍然
dp入門 專題記錄 2017-7-26
開始 com 結束時間 opened long cout 方程 log star POJ3176-Cow Bowling 題目大意:現有n行數,以金字塔的形式排列,即第一行一個數字,第二行2個數字,依次類推,現在需要找一條從第一層到第n層的路線,使得該路線上的所有點的權值
17.07.26 Oracle安裝
nbsp ins 系統 rep lsnrctl 事務 plus acl 網絡 修改主機名: 在root用戶下, hostname node1.test.com vi /etc/sysconfig/network vi /etc/hosts vi ~
17-8-26-WebApp總結
信息 新頁面 返回值 response 一段 一個 不同 嵌入 str 最近學習了在js中連接和用sql語句操作數據庫,學習了ajax的異步提交請求和返回響應,學習了jason數據轉string和jade的語法與連接到response,學習了web應用的開發全過程,學
17/9/6 bootstrap.css去掉後引發的樣式錯亂
bsp str 沖突 模塊 osi 樣式 表現 使用 padding 最近寫的新官網的項目一直都是用的bootstrap的框架,今天的的頁面其中一個模塊使用的插件和bootstrap沖突,當把bootstrap.css去掉後,頁面中的部分樣式發生了錯亂 主要表現為mar
9.26模擬賽
code left ostream 進行 類型 科技 logs 背景 不但 NOIP 2017 全真模擬沖刺 ---LRH&&XXY 題目名稱 那些年 鐵路計劃
C#學習2017-9-26(讀取文本文件和讀取二進制文件)Notes9
text reader 技術分享 com c# 技術 ges utf not 讀寫文本文件:StreamReader類和StreamWriter類 StreamReader類派生自TextReader類,使用StreamReader類讀取標準文本文件的各自信息,Stre
9-26
osi 想要 nbsp 到你 他也 模塊 css 國務院 加油 昨天老師講了css布局position的用法,讓一個一個的模塊可以更靈活的移動到你想讓它去的地方。布置了一個作業,做國務院網頁100%的還原。多我來說這個思路是有的,但是就是細節的東西用的不好,好多標簽都
課後作業17.10.26
函數 pack ring 實驗 順序 style package ret blog 石家莊鐵道大學信息科學與技術學院 2017年----2018年 第一學期 專 業: 軟件工程
20180524早課記錄17-Hadoop
Hadoop1.MapReduce談談你們的理解 執行引擎 計算 2.Map是什麽 map:映射函數 3.Reduce是什麽 reduce:規約函數 4.shuffle談談你們的理解 相當於洗牌 按key進行分組 5.wordcount那副圖,腦子是否有印象? 不太深入 6.輸入分片一般和什麽有關?多少個分片
上周熱點回顧(9.17-9.23)
華為 best 機房 new 2個 inux arch 生產 分布式系 熱點隨筆: · 積極參與開源項目,促進.NET Core生態社區發展(張善友)· 給剛工作不久的程序猿同學的一封信(虛無境)· 一個小時學會Maven(張果)
【蒟蒻周報】思維與結論的碰撞 9.17-9.23
fields 互不侵犯king tips sco 基本 logs lin 計算 html 周出題解 「NOIP2018模擬9.17」線段樹 - 思路題 「BZOJ2190」[SDOI2008] 儀仗隊 - 歐拉函數 「NOIP2018模擬9.18」最近公共祖先 - 結論題
2018.9.26 如何對List集合中的元素進行排序?
lec str 有時 etag gets sets ava int private Collections對List集合中的數據進行排序 有時候需要對集合中的元素按照一定的規則進行排序,這就需要用到 Java中提供的對集合進行操作的工具類Collections,其中的sor
9-26 文件操作
aaa div pen -a context 讀寫 nice ini nco 文件操作 哈哈哈.txt 1.文件路徑:C:\Users\Administrator\Desktop\哈哈哈.txt 2.編碼方式:utf-8、gbk。。。 3
9.26
fix 就是 ont line 權重 繼承性 發送 nbsp pos 標簽 (1) 需要大家記,單標簽和雙標簽 (2) 性能上 塊標簽和行標簽 (3) 標簽的屬性 Css (1) 選擇器,* 標
18.9.26日記
tps think 感受 考試 基環樹dp 幾何 表達式 發現 今天 前言: 繼續考試,今天第一題剛到了10:30,第二題原題(未打過),第三題沒看,心裏很開心,本以為可以拿200分了,結果只有20分,唉,太菜了。 第一題(計算幾何水題,0分,已改): 不知道一個水題後加個
[ 9.26 ]CF每日一題系列—— 771B遞推問題
std ret 重名 () while 字數 har rip ace Description: 給定你命名的規律,1-10個字符,開頭必須大寫,最多有50個名字,然後告訴你有n個人,判斷區間長度為k,那麽你將得到n - k + 1個答案(YES or NO) 表示1 -
9.26日PHP面向對象編程
php 權限 修飾 面向對象 font pad cti 另一個 fun 面向對象三大特性:封裝 繼承 多態 類與對象 類:是一個抽象的概念 對象:是一個具體的實例 在面向對象的語法中,則情況就發生變化了: 1,定義類;定義類的語法中,只有這3種代碼: 1.1定
9-26上課簡記(C語言概述)
第一章 概述 1.語言的發展 機器語言,組合語言,高階語言(分別舉了例子),並講述了諸如Visual C++6.0和CodeBlocks這些編譯器的作用(充當翻譯官); 談了C語言的由來,以C語言的發明人裡奇的故事激勵大家; 2.漢語和C語言的對比 漢字集合——>詞(專有名詞)——&g