給定乙個整數陣列和乙個整數 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 協議,這些函式的呼叫流程都有所區別,這裡先對每個...