基礎類型題 oj 篇3

1、乘積最大子序列

給定一個整數數組 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)

示例1
輸入: [2,3,-2,4]
輸出: 6
解釋: 子數組 [2,3] 有最大乘積 6

示例2
輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能爲 2, 因爲 [-2,-1] 不是子數組

注意事項:比較典型的錯誤思維

    def maxProduct(self, nums: List[int]) -> int:
        n = len(nums)
        dp_max = [nums[0]]*n
        res = nums[0]
        for i in range(1,n):  
            dp_max[i] = max(dp_max[i-1]*nums[i], nums[i])
            res = max(res,dp_max[i])           
        return res

如果計算的最大子序列和,這種思路就是對的。

存在一種情況是,負數乘以負數得到的是正數
就比如下面案列

案列3:[-2,3,-4]

如果返回的是3,就錯了,最大子序列積應該是 24

所以在遍歷的時候,不應該保存最大值,同時也把最小值保存下來,說不定下一個數是負數,然後就把最小的數變爲最大的數了

參考 code

    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        int a = 1,b=1;
        int maxVal = INT_MIN;
        for(int i = 0;i<n;++i){
            int aa = a * nums[i];
            int bb = b * nums[i];

            a = min(nums[i],min(aa,bb));
            b = max(nums[i],max(aa,bb));
            maxVal = max(maxVal,b);
        }
        return maxVal;
    }

2、尋找峯值

峯值元素是指其值大於左右相鄰值的元素

給定一個輸入數組 nums,其中 nums[i] ≠ nums[i+1],找到峯值元素並返回其索引。

數組可能包含多個峯值,在這種情況下,返回任何一個峯值所在位置即可。

你可以假設 nums[-1] = nums[n] = -∞

說明:你的解法應該是 O(logN) 時間複雜度的

示例1
輸入: nums = [1,2,3,1]
輸出: 2
解釋: 3 是峯值元素,你的函數應該返回其索引 2。

示例2
輸入: nums = [1,2,1,3,5,6,4]
輸出: 1 或 5
解釋: 你的函數可以返回索引 1,其峯值元素爲 2;
或者返回索引 5, 其峯值元素爲 6。

思路一:O(n) 的時間複雜度進行遍歷

思路二:二分查找,我們知道二分查找是用於有序數據,但是這些數據完全都是無序的呀,而且不可能排序,排序就無法正確返回峯值下標。

那是因爲我們之前二分查找是中間數據和左(右)邊數據比較的,這次我們用 mid 和 mid + 1 比較

    def findPeakElement(nums) :
        left,right = 0,len(nums)-1
        while left<right:
            mid = (left+right)//2
            # 如果右邊大於左邊說明還沒到達峯值
            if nums[mid]<nums[mid+1]:
                left = mid+1
            else:
                right = mid
        return left

7.求衆數

給定一個大小爲 n 的數組,找到其中的衆數。衆數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素

你可以假設數組是非空的,並且給定的數組總是存在衆數。

示例1
輸入: [3,2,3]
輸出: 3

示例2
輸入: [2,2,1,1,1,2,2]
輸出: 2

思路一:排序後取出中間的數據

思路二:藉助字典進行計數的方式來判斷衆數,空間複雜度爲O(N)

    def majorityElement(self, nums: List[int]) -> int:
        dic = {}
        if len(nums)==1:
            return nums[0]
        for i in range(len(nums)):
            if nums[i] not in dic:
                dic[nums[i]] = 1
            else:
                dic[nums[i]]+=1
                if dic[nums[i]]>len(nums)//2:
                    return nums[i]

思路三:通過計數的方式,先用一個變量保存第一個值,並計數爲1,如果下一個值和變量值相等,則計數 +1,如果不相等則計數 -1,如果計數 等於 0 的時候,把下一個值賦值給該變量,最後返回變量的值,它一定是衆數

核心思想就是將衆數和不是衆數的次數抵消了,然後最後一個數一定是衆數了

參考代碼

    def majorityElement(self, nums: List[int]) -> int:
        n = len(nums)
        ans = nums[0]
        time = 1 # 次數
        for i in range(1,n):
            if time == 0:
                ans = nums[i]
            if ans == nums[i]:
                time+=1
            else:
                time-=1
        return ans

8.最大間距

給定一個無序的數組,找出數組在排序之後,相鄰元素之間最大的差值

如果數組元素個數小於 2,則返回 0

示例1
輸入: [3,6,9,1]
輸出: 3
解釋: 排序後的數組是 [1,3,6,9], 其中相鄰元素 (3,6) 和 (6,9) 之間都存在最大差值 3。

示例2
輸入: [10]
輸出: 0
解釋: 數組元素個數小於 2,因此返回 0。

思路一:排序後進行判斷

    def maximumGap(self, nums: List[int]) -> int:
        if not nums or len(nums)<2:
            return 0
        nums.sort()
        max_num = 0
        n = len(nums)
        for i in range(1,n):
            max_num = max(nums[i]-nums[i-1],max_num)
        return max_num

思路二:桶排序的原理

10.階乘後的零

給定一個整數 n,返回 n! 結果尾數中零的數量。

示例1
輸入: 3
輸出: 0
解釋: 3! = 6, 尾數中沒有零。

示例1
輸入: 5
輸出: 1
解釋: 5! = 120, 尾數中有 1 個零.

只有5*2可以得到0

只要有偶數就能分解出2,2的個數一定比5多,所以只用計算5的個數
對於20來說,只有5,10,15,20包含5,故20!結尾有20/5=4個零

當然不止這麼簡單,對於25來說:只有5,10,15,20,25,包含5,結尾卻有6個零,因爲25=5x5,包含兩個5

所以 f(n)=n/5+f(n/5)

    def trailingZeroes(self, n: int) -> int:
        if n<5:
            return 0
        if n<10:
            return 1
        return int(n/5) + self.trailingZeroes(int(n/5))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章