Leetcode程式設計實踐 查詢 滑動陣列 二分查詢

2021-10-24 04:16:57 字數 4733 閱讀 4150

給定乙個整數陣列和乙個整數 k,判斷陣列中是否存在兩個不同的索引 i 和 j,使得 nums [i] = nums [j],並且 i 和 j 的差的 絕對值 至多為 k。

【思路】

使用長度為k的滑動視窗查詢,若視窗內去重元素小於k,則返回true,否則繼續滑動。

class

solution

:def

containsnearbyduplicate

(self, nums: list[

int]

, k:

int)

->

bool

: record=

set(

)# 滑動視窗元素集合

for i in

range

(len

(nums)):

if nums[i]

in record:

return

true

record.add(nums[i])if

len(record)

>k:

# 當集合元素超出k時,刪除最左側元素,向右滑動

record.remove(nums[i-k]

)return

false

在整數陣列 nums 中,是否存在兩個下標 i 和 j,使得 nums [i] 和 nums [j] 的差的絕對值小於等於 t ,且滿足 i 和 j 的差的絕對值也小於等於 ķ 。

如果存在則返回 true,不存在返回 false。

【思路】

暴力法:兩重迴圈o(n^2)

二分查詢法:目標數字區間為v-t<=x<=v+t,因為集合為有序陣列,故可以使用二分查詢(有序就想到二分查詢)對record進行查詢,先查詢大於等於下界的最小數,在判斷是否小於等於上界。

class

solution

:def

containsnearbyalmostduplicate

(self, nums: list[

int]

, k:

int, t:

int)

->

bool

: record=

set(

)# 滑動視窗集合

for i in

range

(len

(nums)):

iflen

(record)

>0:

r=list

(record)

idx=self.get(r,nums[i]

-t)# 對集合進行二分查詢,查詢大於等於下界最小元素的座標

if idx!=-1

and r[idx]

<=nums[i]

+t:# 在判斷是否小於等於上界

return

true

record.add(nums[i])if

len(record)

>k:

record.remove(nums[i-k]

)return

false

# 二分查詢函式

defget

(self,l,t)

: i,j=0,

len(l)-1

while imid=

(j+i)//2

# 臨界點

if l[mid]

i=mid+

1else

: j=mid

return i if l[i]

>=t else-1

# 若集合中無目標數字,則返回-1

def

erfen

(arr)

:# 低一點

i,j =0,

len(arr)-1

while imid =

(i+j)//2

# 第二點

if f(x)

: i=mid+

1else

: j=mid

return i

【解釋】

第一點:i 和 j 分別對應搜尋的上界和下界,但不一定為0和arr最後乙個點的下標;

第二點:f(x) 為查詢條件,帶入模板即可。

給定乙個排序陣列和乙個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。

你可以假設陣列中無重複元素。

【思路】

排序陣列→二分查詢

class

solution

:def

searchinsert

(self, nums: list[

int]

, target:

int)

->

int:

i,j=0,

len(nums)

# 此處末端設為len(nums) 是由於插入的數字為最大值 需要插入在最外面

while im=

(i+j)//2

if nums[m]

==target:

return m

elif nums[m]

>target:

j=melse

: i=m+

1return i

給定乙個只包含整數的有序陣列,每個元素都會出現兩次,唯有乙個數隻會出現一次,找出這個數。

【思路】

二分查詢,若子集長度為單數則存在單一元素,對於該子集呼叫遞迴函式繼續查詢。

class

solution

:def

singlenonduplicate

(self, nums: list[

int])-

>

int:

iflen

(nums)==1

:return nums[0]

# 邊界條件

i,j=0,

len(nums)-1

m=(i+j)//2

if nums[m]

!=nums[m-1]

and nums[m]

!=nums[m+1]

:return nums[m]

elif nums[m]

==nums[m+1]

:if m%2==

1:return self.singlenonduplicate(nums[

:m])

else

:return self.singlenonduplicate(nums[m+2:

])elif nums[m]

==nums[m-1]

:if(m-1)%

2==1:

return self.singlenonduplicate(nums[

:m-1])

else

:return self.singlenonduplicate(nums[m+1:

])

給定乙個非負整數陣列和乙個整數 m,你需要將這個陣列分成 m 個非空的連續子陣列。設計乙個演算法使得這 m 個子陣列各自和的最大值最小。

輸入:nums = [7,2,5,10,8]

m = 2

輸出:18

解釋:一共有四種方法將nums分割為2個子陣列。

其中最好的方式是將其分為[7,2,5] 和 [10,8],

因為此時這兩個子陣列各自的和的最大值為18,在所有情況中最小。

【思路】

目標值位於max(nums)和sum(nums)之間,對該區間使用二分查詢;

查詢條件為:子陣列求和<=目標值,可以分割出的最大子集數量(可定義輔助函式表達),要求該數量=m。

class

solution

:def

splitarray

(self, nums: list[

int]

, m:

int)

->

int:

# 尋找查詢目標的輔助函式

defhelper

(x):

res,tmp=0,

0for num in nums:

if num+tmp<=x:

# 區間和不大於目標值

tmp+=num

else

: res+=

1 tmp=num

return res+

1

i,j=

max(nums)

,sum

(nums)

while imid=

(i+j)//2

if helper(mid)

>m:

i=mid+

1else

: j=mid

return i # i為滿足條件的下界,即為所求最小最大值

【總結】

最大最小值問題,最小最大值問題都可以使用二分查詢思想

程式設計實踐

1 輸入乙個長度小於100的字串,判斷其是否為回文串。先上 include includeusing namespace std string abc int len bool ispalindrome true 定義乙個布林變數,用來記錄字串是否是回文串 bool ispalind string ...

《C語言及程式設計》實踐專案 查詢和排序

返回 賀老師課程教學鏈結 專案1 有幾個 請程式設計序,輸入若干個正數 不超過100個,以0結束 儲存在陣列中。再輸入乙個正數n,輸出n在前面出現過多少次?參考解答 專案2 二分法解方程 二分法是在電腦科學中很重要的一種方法,用於查詢產生二分查詢演算法,還可以用在很多場合。可以用二分法解方程。對於區...

socket程式設計實踐

socket程式設計 1 函式說明。socket 程式設計的基本函式有 socket bind listen accept send sendto recv 以及 recvfrom 等,其中根據客戶端還是服務端,或者根據使用 tcp 協議還是 udp 協議,這些函式的呼叫流程都有所區別,這裡先對每個...