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))