刷leetCode算法題+解析(二十五)

Fizz Buzz

題目:寫(xiě)一個(gè)程序,輸出從 1 到 n 數(shù)字的字符串表示。1. 如果 n 是3的倍數(shù),輸出“Fizz”;2. 如果 n 是5的倍數(shù),輸出“Buzz”;3.如果 n 同時(shí)是3和5的倍數(shù),輸出 “FizzBuzz”。

示例:
n = 15,
返回:
[
"1",
"2",
"Fizz",
"4",
"Buzz",
"Fizz",
"7",
"8",
"Fizz",
"Buzz",
"11",
"Fizz",
"13",
"14",
"FizzBuzz"
]

思路:這個(gè)題怎么說(shuō)呢。應(yīng)該是很簡(jiǎn)單的啊,沒(méi)坑的話一個(gè)循環(huán)搞定,是3,5的倍數(shù)輸出FizzBuzz,是3倍數(shù)輸出Fizz是5倍數(shù)輸出Buzz,不是輸出字符串本身。我去做做看坑在哪里

class Solution {
    public List<String> fizzBuzz(int n) {
        List<String> res = new ArrayList<String>();
        for(int i=1;i<=n;i++){
            if(i%3==0 && i%5==0){
                res.add("FizzBuzz");
            }else if(i%3==0){
                res.add("Fizz");
            }else if(i%5==0){
                res.add("Buzz");
            }else{
                res.add(i+"");
            }
        }
        return res;       
    }
}

額,有點(diǎn)尷尬,一次做完,都沒(méi)發(fā)現(xiàn)有坑,我可能是讓LeetCode坑的有了被害妄想癥了。因?yàn)檫@個(gè)性能也不錯(cuò),所以直接這樣了,下一題。

第三大的數(shù)

題目:給定一個(gè)非空數(shù)組,返回此數(shù)組中第三大的數(shù)。如果不存在,則返回?cái)?shù)組中最大的數(shù)。要求算法時(shí)間復(fù)雜度必須是O(n)。

示例 1:
輸入: [3, 2, 1]
輸出: 1
解釋: 第三大的數(shù)是 1.
示例 2:
輸入: [1, 2]
輸出: 2
解釋: 第三大的數(shù)不存在, 所以返回最大的數(shù) 2 .
示例 3:
輸入: [2, 2, 3, 1]
輸出: 1
解釋: 注意,要求返回第三大的數(shù),是指第三大且唯一出現(xiàn)的數(shù)。
存在兩個(gè)值為2的數(shù),它們都排第二。

思路:這道題第一反應(yīng)排序,估計(jì)直接sort之類(lèi)的有點(diǎn)問(wèn)題,我先理理思路:大體上分兩種情況,有第三大的返回第三大的。沒(méi)第三大的返回最大的。其實(shí)又有那個(gè)想法了:不考慮性能的話怎么都能做出來(lái)!不管是list,map,還是數(shù)組都可以做到。就是里面三個(gè)不同元素,遍歷數(shù)組每一個(gè)比較大小,小于已有的三個(gè)則繼續(xù)往下,大于已有的三個(gè)依次比較,保證存儲(chǔ)的元素是最大的三個(gè)就行了。我覺(jué)得這個(gè)思路可以實(shí)現(xiàn),就是不知道性能怎么樣,我去試試。
事實(shí)證明剛剛的想法是可行的,就是性能確實(shí)不怎么地,先上代碼:

class Solution {
    public int thirdMax(int[] nums) {
        Map<Integer,Long> map = new HashMap<Integer,Long>();
        map.put(1,-3000000000l);
        map.put(2,-3000000000l);
        map.put(3,-3000000000l);
        for(int i = 0 ;i<nums.length;i++){
            if(nums[i]>map.get(3)){
                if(map.get(1)<nums[i]){
                    map.put(3,map.get(2));
                    map.put(2,map.get(1));
                    map.put(1,(long)nums[i]);
                }else if(map.get(2)<nums[i] && nums[i]!=map.get(1)){
                    map.put(3,map.get(2));
                    map.put(2,(long)nums[i]);
                }else if(map.get(3)<nums[i] && nums[i]!=map.get(2) && nums[i]!=map.get(1)){
                    map.put(3,(long)nums[i]);
                }
            }
        }
        return map.get(3)==-3000000000l?map.get(1).intValue():(int)map.get(3).intValue();
    }
}

啰里啰嗦的,事實(shí)證明我還年輕,所以沒(méi)想到測(cè)試案例第三的值會(huì)是int的最小值,卡了好久。
然后我這用的map,但是我估計(jì)數(shù)組,list 都可以,具體哪個(gè)性能好也不知道,但是我覺(jué)得應(yīng)該是數(shù)組比較好,我去試試:

class Solution {
    public int thirdMax(int[] nums) {
        long[] res = new long[3];
        res[0] = -3000000000l;
        res[1] = -3000000000l;
        res[2] = -3000000000l;
        for(int i = 0 ;i<nums.length;i++){
            if(nums[i]>res[2]){
                if(res[0]<nums[i]){
                    res[2] = res[1];
                    res[1] = res[0];
                    res[0] = nums[i];
                }else if(res[1]<nums[i] && nums[i]!=res[0]){
                    res[2] = res[1];
                    res[1] = nums[i];
                }else if(res[2]<nums[i] && nums[i]!=res[1] && nums[i]!=res[0]){
                    res[2] = nums[i];
                }
            }
        }
        return res[2]==-3000000000l?(int)res[0]:(int)res[2];
    }
}

嗯,換了數(shù)組確實(shí)性能一下子上來(lái)了,超過(guò)百分之九十九的用戶,所以這道題就這樣,下一題吧。

字符串相加

題目:給定兩個(gè)字符串形式的非負(fù)整數(shù) num1 和num2 ,計(jì)算它們的和。
num1 和num2 的長(zhǎng)度都小于 5100.
num1 和num2 都只包含數(shù)字 0-9.
num1 和num2 都不包含任何前導(dǎo)零。
你不能使用任何內(nèi)建 BigInteger 庫(kù), 也不能直接將輸入的字符串轉(zhuǎn)換為整數(shù)形式。

思路:很好,又沒(méi)看懂題目,這個(gè)不能使用BigInteger可以理解,還不能轉(zhuǎn)化整數(shù)是什么意思?for循環(huán)每一個(gè)字符相加不行么?有點(diǎn)費(fèi)解,我去用測(cè)試案例試試什么意思

image.png

很好,明白題意了,就是從最后一位開(kāi)始兩個(gè)字符串一個(gè)個(gè)字符相加。而且題目簡(jiǎn)直有毛病。長(zhǎng)度5100以內(nèi),還用特意聲明不轉(zhuǎn)化成int?也得能轉(zhuǎn)化才行啊。其實(shí)這樣看思路清晰多了,我去擼代碼了。

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder sb = new StringBuilder();
        int carry = 0;
        int i = num1.length()-1; 
        int j = num2.length()-1;
        while(i >= 0 || j >= 0 || carry != 0){
            if(i>=0) carry += num1.charAt(i--)-'0';
            if(j>=0) carry += num2.charAt(j--)-'0';
            sb.append(carry%10);
            carry /= 10;
        }
        return sb.reverse().toString();
    }
}

在多次循環(huán)并且越寫(xiě)越墨跡以后,我選擇了直接嫖大神代碼:對(duì),就是如圖所示,簡(jiǎn)單易懂,我就很納悶同樣的大腦為啥思路差這么多呢(手動(dòng)滑稽)。
反正如圖,做的很好,如果進(jìn)位了,carry/10還會(huì)是1,這樣自動(dòng)進(jìn)位了,不然不足10會(huì)是0,相當(dāng)于重置計(jì)算下一位數(shù)字。
而且大神說(shuō)了,適用于十進(jìn)制,二進(jìn)制,任何進(jìn)制(只不過(guò)參數(shù)要改,但是思路不變。前提是不考慮負(fù)數(shù))。
反正方法就是這么個(gè)方法,代碼也就是這么幾行代碼。我是存在u盤(pán)里了,覺(jué)得真的挺經(jīng)典的,除了膜拜沒(méi)啥說(shuō)的。繼續(xù)往下吧,現(xiàn)在一篇目標(biāo)5+題。

字符串中的單詞數(shù)

題目:統(tǒng)計(jì)字符串中的單詞個(gè)數(shù),這里的單詞指的是連續(xù)的不是空格的字符。請(qǐng)注意,你可以假定字符串里不包括任何不可打印的字符。

示例:
輸入: "Hello, my name is John"
輸出: 5

思路:這個(gè)題說(shuō)真的,類(lèi)似的做了好多好多遍了,好像是不能直接用split?我忘了有啥潛含的要求了,反正我現(xiàn)在賊煩這種題目上看不出來(lái)的限制。我就按照我自己的想法做一遍,通過(guò)了的話剩下題解見(jiàn)吧。對(duì)了這個(gè)題好像也可以是所有莫名其妙的符號(hào)轉(zhuǎn)換成空格。比如什么逗號(hào)句號(hào)問(wèn)號(hào)啥的,我先去做做再說(shuō)

很好,這個(gè)題很清新脫俗不拘一格別出心裁反正完全讓人意想不到。大概講一下幾個(gè)坑:關(guān)于這個(gè)空格,不是空字符串,是space這個(gè)空格,關(guān)于這兩個(gè)是有區(qū)別的:
空格和空字符串

然后繼續(xù)往下,這個(gè), , ,這算是三個(gè)單詞,出題人腦回路6666.然后一開(kāi)始split不行,換了個(gè)思路,我直接上代碼:

class Solution {
    public int countSegments(String s) {
        char [] ch = s.toCharArray();
        int res = 0;
        int temp = 0;
        for(int i=0;i<s.length();i++ ){
            if(!Character.isSpace(ch[i])){
                temp++;
            }else{
                if(temp!=0) {
                    res += 1;
                }
                temp=0;
            }
        }
        return temp==0?res:res+1;
    }
}

說(shuō)實(shí)話判斷邏輯挺無(wú)腦的,就是有不是空格的就計(jì)數(shù),遇到空格說(shuō)明總數(shù)+1.如果遇到空格發(fā)現(xiàn)計(jì)數(shù)為0說(shuō)明多個(gè)空格在一起了,不算是單詞。一直遍歷到最后,判斷最后計(jì)數(shù)上是不是0,是0說(shuō)明空格結(jié)尾,之前有多少單詞返回多少,不是0說(shuō)明最后的單詞還沒(méi)算,所以要+1.
整體邏輯就這樣,因?yàn)橹苯有阅馨俜职?,所以直接下一題。

路徑總和三

題目:給定一個(gè)二叉樹(shù),它的每個(gè)結(jié)點(diǎn)都存放著一個(gè)整數(shù)值。找出路徑和等于給定數(shù)值的路徑總數(shù)。路徑不需要從根節(jié)點(diǎn)開(kāi)始,也不需要在葉子節(jié)點(diǎn)結(jié)束,但是路徑方向必須是向下的(只能從父節(jié)點(diǎn)到子節(jié)點(diǎn))。二叉樹(shù)不超過(guò)1000個(gè)節(jié)點(diǎn),且節(jié)點(diǎn)數(shù)值范圍是 [-1000000,1000000] 的整數(shù)。
image.png

思路:二叉樹(shù)的題,主思路遞歸/迭代。我習(xí)慣性遞歸。首先判斷例子可以看出幾點(diǎn)1.樹(shù)節(jié)點(diǎn)不唯一。2.樹(shù)節(jié)點(diǎn)沒(méi)有規(guī)律,什么左小右大都沒(méi)有,正負(fù)也是。 3.本來(lái)我預(yù)計(jì)的是某條線到了給定數(shù)字就清0從來(lái),但是現(xiàn)在看不行,很有可能到了給定數(shù)字然后往下加個(gè)正數(shù)減個(gè)負(fù)數(shù)啥的又變成了這個(gè)數(shù)字。這就有點(diǎn)問(wèn)題了,暫時(shí)沒(méi)有啥思路,我去理理
好吧,沒(méi)理出來(lái),雖然知道是遞歸但是具體怎么做一點(diǎn)思路沒(méi)有,所以直接看了官方的題解,不得不說(shuō)看了題解豁然開(kāi)朗,然后我先把題解大概說(shuō)一下:

  • 路徑的開(kāi)頭可以不是根節(jié)點(diǎn),結(jié)束也可以不是葉子節(jié)點(diǎn),是不是有點(diǎn)復(fù)雜?
    如果問(wèn)題是這樣:找出以根節(jié)點(diǎn)為開(kāi)始,任意節(jié)點(diǎn)可作為結(jié)束,且路徑上的節(jié)點(diǎn)和為 sum 的路徑的個(gè)數(shù);
  • 是不是前序遍歷一遍二叉樹(shù)就可以得到所有這樣的路徑?是的;
    如果這個(gè)問(wèn)題解決了,那么原問(wèn)題可以分解成多個(gè)這個(gè)問(wèn)題;
  • 是不是和數(shù)線段是同一個(gè)問(wèn)題,只不過(guò)線段變成了二叉樹(shù);
    在解決了以根節(jié)點(diǎn)開(kāi)始的所有路徑后,就要找以根節(jié)點(diǎn)的左孩子和右孩子開(kāi)始的所有路徑,三個(gè)節(jié)點(diǎn)構(gòu)成了一個(gè)遞歸結(jié)構(gòu);
  • 遞歸真的好簡(jiǎn)單又好難;

然后看了這個(gè)題的解釋豁然開(kāi)朗,我去試著寫(xiě)寫(xiě)代碼:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int pathSum(TreeNode root, int sum) {
        if(root==null) return 0;
        return pathNode(root,sum)+pathSum(root.right,sum)+pathSum(root.left,sum);

    }
    public int pathNode(TreeNode root,int sum){
        if(root==null) return 0;
        int res = 0;
        if(root.val==sum) res += 1;
        return res+pathNode(root.right,sum-root.val)+pathNode(root.left,sum-root.val); 
    }

如圖所示,兩個(gè)遞歸。要調(diào)試瘋了,反正沒(méi)技術(shù),沒(méi)技巧,我就一點(diǎn)點(diǎn)打印調(diào)試。等做出來(lái)了才發(fā)現(xiàn)其實(shí)也沒(méi)那么簡(jiǎn)單。就是每一個(gè)節(jié)點(diǎn)的符合條件的路徑數(shù),然后再遞歸把所有的加在一起。但是我這么寫(xiě)性能不咋地,我去看看性能好的寫(xiě)法:
算了看了性能好的寫(xiě)法有點(diǎn)看不懂,而且剛剛不斷調(diào)試那個(gè)雙遞歸也頭暈,換下一道題換個(gè)心情吧。能自己做出來(lái)我就挺滿意了,不追求完美了。

排列硬幣

題目:你總共有 n 枚硬幣,你需要將它們擺成一個(gè)階梯形狀,第 k 行就必須正好有 k 枚硬幣。給定一個(gè)數(shù)字 n,找出可形成完整階梯行的總行數(shù)。n 是一個(gè)非負(fù)整數(shù),并且在32位有符號(hào)整型的范圍內(nèi)。

示例 1:
n = 5
硬幣可排列成以下幾行:
¤
¤ ¤
¤ ¤
因?yàn)榈谌胁煌暾?,所以返?.
示例 2:
n = 8
硬幣可排列成以下幾行:
¤
¤ ¤
¤ ¤ ¤
¤ ¤
因?yàn)榈谒男胁煌暾?,所以返?.

思路:很喜歡這種一個(gè)簡(jiǎn)單一個(gè)難的題目啊,這道題又是送分題,不就是判斷一個(gè)數(shù)字拆成1,2,3,。。最多能拆到幾么。我去寫(xiě)代碼了

class Solution {
    public int arrangeCoins(int n) {
        int i = 1;
        while(n>=i){
            n=n-i;
            i++;
        }
        return i-1;
    }
}

一次搞定,雖然性能不行。不過(guò)在寫(xiě)的時(shí)候就有了隱隱約約的貌似有什么規(guī)律的感覺(jué)。第一行+倒數(shù)第二行是倒數(shù)第一行(這里忽略了不滿的最后一行)第二行加倒數(shù)第三行也是最后一行,第三行加倒數(shù)第四行。。以此類(lèi)推,肯定是有規(guī)律的,我去“看”規(guī)律了!
算了,手頭沒(méi)筆和紙,還是在這里打字吧:第n行,前面有n-1除2的n,如果是偶數(shù)還會(huì)有個(gè)中間的二分之n的數(shù),再加上本身的 第n行,嗯嗯,有道理,我還是直接看題解吧。哈哈,覺(jué)得沒(méi)啥必要非要手算,知道有規(guī)律就行了我覺(jué)得。

image.png

諾,如圖,我還是喜歡拿現(xiàn)成的。
今天的筆記就做到這里,如果稍微幫到你了記得點(diǎn)個(gè)喜歡點(diǎn)個(gè)關(guān)注呦!也祝大家工作順順利利!順便說(shuō)個(gè)題外話,力扣1298道題,到了今天我終于把尾數(shù)做完了,開(kāi)心~~雖然我知道以后中等難度和困難難度肯定不會(huì)做的這么快了,但還是覺(jué)得有奔頭!嘿嘿

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 有效的完全平方數(shù) 題目:給定一個(gè)正整數(shù) num,編寫(xiě)一個(gè)函數(shù),如果 num 是一個(gè)完全平方數(shù),則返回 True,否...
    唯有努力不欺人丶閱讀 807評(píng)論 0 2
  • 1. 找出數(shù)組中重復(fù)的數(shù)字 題目:在一個(gè)長(zhǎng)度為n的數(shù)組里的所有數(shù)字都在0到n-1的范圍內(nèi)。數(shù)組中某些數(shù)字是重復(fù)的,...
    BookThief閱讀 2,016評(píng)論 0 2
  • 有效的字母異位詞 題目:給定兩個(gè)字符串 s 和 t ,編寫(xiě)一個(gè)函數(shù)來(lái)判斷 t 是否是 s 的字母異位詞。 示例 1...
    唯有努力不欺人丶閱讀 317評(píng)論 0 4
  • 前言 2. 實(shí)現(xiàn) Singleton 3. 數(shù)組中重復(fù)的數(shù)字 4. 二維數(shù)組中的查找 5. 替換空格 6. 從尾到...
    Observer_____閱讀 3,163評(píng)論 0 1
  • 這幾天做課代表,嚯,一周不到兩天忘了接娃~ (班班營(yíng)銷(xiāo)技巧真不錯(cuò),很能聊,也特別專(zhuān)業(yè),是我喜歡的類(lèi)型呢!) 和娃矛...
    一直長(zhǎng)大的小幸福閱讀 255評(píng)論 0 1

友情鏈接更多精彩內(nèi)容