C++/Java小白解Leetcode題,發現了知識盲區……

Charzueus發表於2020-12-02

我的部落格園:https://www.cnblogs.com/chenzhenhong/p/14072684.html

我的CSDN部落格:https://blog.csdn.net/Charzous/article/details/110355827


 

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。
本文連結:https://blog.csdn.net/Charzous/article/details/110355827

一、初見LeetCode

大一時候學習C++,根據課程一直在PTA平臺做題目,資料結構和演算法的作業題目也是在PTA。後來發現牛客網學習資源也很豐富,孤陋寡聞,前幾個月在知道LeetCode這個平臺,跟牛客網可以並稱“程式設計師的左膀右臂”๑乛◡乛๑。雖然認識了LeetCode,但是一直擠出時間過來練練題,仰慕一下各位大佬的AC。今天就試了幾道題,發現風格與PTA有很大不同,還需要不斷去熟悉,別具風格的打題也挺有意思,通過幾個簡單題目,發現自己知識盲區,希望能夠學習到更多!下面記錄一下幾個題目的思路解法。

二、字串中的單詞數

題目:

統計字串中的單詞個數,這裡的單詞指的是連續的不是空格的字元。

請注意,你可以假定字串裡不包括任何不可列印的字元。

示例:

  1.  
    輸入: "Hello, my name is John"
  2.  
    輸出: 5
  3.  
    解釋: 這裡的單詞是指連續的不是空格的字元,所以 "Hello," 算作 1 個單詞。

題解:

class Solution {
    public int countSegments(String s) {
        int count=0;
        s=s.trim();
        if(s.equals(""))
            count=0;
        else
        {
            
            String[] word=s.trim().split("\\s+");
            count=word.length;
        }
        return count;
    }
}

開始直接想到Java的函式,對這道題可以簡單處理,容易解決。不過期間有幾個注意點,就是處理連續空格和邊界情況。

後來嘗試C++手寫方法,效果更好:

image.png

 思路:使用一個flag標識每個單詞分界點,如果當前字元不是空格且它前一個為空格(即此處分隔單詞邊界),則計數新單詞個數。

class Solution {
public:
    int countSegments(string s) {
        int flag=1,count=0;
        for(int i=0;i<s.length();i++)
        {
            if(s[i]!=' '&&flag) 
            {
                count++;
                flag=0;
            }    
            if(s[i]==' ')
                flag=1;
        }
        return count;
    }
};
/*
作者:lu-hai-pan-jiang
連結:https://leetcode-cn.com/problems/number-of-segments-in-a-string/solution/jian-dan-zhi-jie-si-lu-ji-bai-100-by-lu-hai-pan-ji/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
*/

三、最富有客戶的資產總量

給你一個 m x n 的整數網格 accounts ,其中 accounts[i][j] 是第 i​​​​​ 位客戶在第 j 家銀行託管的資產數量。返回最富有客戶所擁有的 資產總量 。

客戶的 資產總量 就是他們在各家銀行託管的資產數量之和。最富有客戶就是 資產總量 最大的客戶。

 

示例 1:

輸入:accounts = [[1,2,3],[3,2,1]]
輸出:6
解釋:
第 1 位客戶的資產總量 = 1 + 2 + 3 = 6
第 2 位客戶的資產總量 = 3 + 2 + 1 = 6
兩位客戶都是最富有的,資產總量都是 6 ,所以返回 6 。


示例 2:

輸入:accounts = [[1,5],[7,3],[3,5]]
輸出:10
解釋:
第 1 位客戶的資產總量 = 6
第 2 位客戶的資產總量 = 10 
第 3 位客戶的資產總量 = 8
第 2 位客戶是最富有的,資產總量是 10


示例 3:

輸入:accounts = [[2,8,7],[7,1,3],[1,9,5]]
輸出:17

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/richest-customer-wealth
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

Hint:

m == accounts.length
n == accounts[i].length
1 <= m, n <= 50
1 <= accounts[i][j] <= 100

這題目是簽到題,思路直接簡單。

class Solution {
    public int maximumWealth(int[][] accounts) {
        int maxV=0;
        for(int i=0;i<accounts.length;i++)
        {
            int sum=0;
            for(int j=0;j<accounts[i].length;j++)
                sum+=accounts[i][j];
            if(maxV<sum)
                maxV=sum;
        }
        return maxV;
    
    }
}

四、三角形的最大周長

給定由一些正數(代表長度)組成的陣列 A,返回由其中三個長度組成的、面積不為零的三角形的最大周長。

如果不能形成任何面積不為零的三角形,返回 0。

示例 1:

輸入:[2,1,2]
輸出:5


示例 2:

輸入:[1,2,1]
輸出:0


示例 3:

輸入:[3,2,3,4]
輸出:10


示例 4:

輸入:[3,6,2,3]
輸出:8
 

提示:

3 <= A.length <= 10000
1 <= A[i] <= 10^6

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/largest-perimeter-triangle
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。 

思路:先將邊長降序排列,從後往前掃描,貪心的思想,取得能夠組成三角形的最大周長。

C++版本:

class Solution {
public:
    int largestPerimeter(vector<int>& A) {
        sort(A.begin(),A.end());
        for(int i=A.size()-1;i>=2;i--)
        {
            if(A[i-2]+A[i-1]>A[i])
                return A[i-2]+A[i-1]+A[i];
        }
        return 0;
    }
};

Java版本:執行用時更短,奇怪了(・。・)

class Solution {
    public int largestPerimeter(int[] A) {
        Arrays.sort(A);
        for(int i=A.length-1;i>=2;i--)
        {
            if(A[i-2]+A[i-1]>A[i])
                return A[i-2]+A[i-1]+A[i];
        }
        return 0;
    }
}

五、找出最具競爭力的子序列(中等難度)

給你一個整數陣列 nums 和一個正整數 k ,返回長度為 k 且最具 競爭力 的 nums 子序列。陣列的子序列是從陣列中刪除一些元素(可能不刪除元素)得到的序列。

在子序列 a 和子序列 b 第一個不相同的位置上,如果 a 中的數字小於 b 中對應的數字,那麼我們稱子序列 a 比子序列 b(相同長度下)更具 競爭力 。 例如,[1,3,4] 比 [1,3,5] 更具競爭力,在第一個不相同的位置,也就是最後一個位置上, 4 小於 5 。

 

示例 1:

輸入:nums = [3,5,2,6], k = 2
輸出:[2,6]
解釋:在所有可能的子序列集合 {[3,5], [3,2], [3,6], [5,2], [5,6], [2,6]} 中,[2,6] 最具競爭力。


示例 2:

輸入:nums = [2,4,3,3,5,4,9,6], k = 4
輸出:[2,3,3,4]
 

提示:

1 <= nums.length <= 105
0 <= nums[i] <= 109
1 <= k <= nums.length

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/find-the-most-competitive-subsequence
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

前面幾道屬於簡單型別,這道中等題目就顯得有些分量了,題目需要琢磨一會才知道是要幹啥,就題做題。

看到一個大佬的解題思路,這個比較好理解:傳送門

維護一個單調棧,從左到右遍歷陣列。

1、如果當前元素比隊尾元素小,接下來判斷剩餘陣列長度(len - i)和目標棧還需要元素個數(k - stack.size() + 1)大小。
     1.1 如果前者小於或等於後者,則說明不能再出棧了,否則剩餘陣列全加進棧也不夠將棧填到k+1長度。(需要k+1而不是k是因為一開始就填進了-1,但這個-1是不會被返回的)
     1.2 如果前者大於後者,就將隊尾元素出棧,並重復第一步

2、如果棧長度不夠,不用判斷,直接將當前元素進棧即可。

class Solution {
     public int[] mostCompetitive(int[] nums, int k) {
 
        Stack<Integer> stack = new Stack<>();
        stack.add(-1);
        int len = nums.length;
 
        for (int i = 0; i < len; i++) {
            //當前元素比隊尾元素小,將隊尾元素出棧
            //此處需要另外判斷陣列剩餘長度夠不夠填滿棧,不然最後答案長度可能會小於k
            while (nums[i] < stack.peek() && k - stack.size() + 1 < len - i) {
                stack.pop();
            }
            if (stack.size() < k + 1) {
                stack.add(nums[i]);
            }
        }
 
        int[] ret = new int[k];
 
        while (k > 0) {
            ret[--k] = stack.pop();
        }
 
        return ret;
    }
}
 
//作者連結:https://leetcode-cn.com/problems/find-the-most-competitive-subsequence/solution/java-dan-diao-zhan-by-thedesalizes/

另外一個圖文講解,輔助理解:傳送門

六、總結

今天一番解題經歷下來,很明顯遇到了最後這道題目就卡住了,說明還不夠熟悉這方面的知識,存在許多盲區。程式語言是一個方面,關鍵在於資料結構和演算法設計上,思路還不夠清晰。所以就此發現了知識的缺漏,之後需要多練習,這麼好的平臺要利用好๑乛◡乛๑,向大佬們學習提高一下程式設計能力。

相關文章