1. 程式人生 > >LintCode 解體記錄 17.9.26

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;

    }

題目描述

給定一個字串矩陣,從裡面找出給定單詞,可以橫著組,豎著組都可以。

思路

經典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