搬石頭排序的最少次數

2021-10-08 06:55:40 字數 1736 閱讀 7217

題目描述:

沙灘擺放著一排大小不一的球形石頭,已知第i個石頭的半徑為ri,不存在兩個石頭半徑相等。現要求通過移動石頭使擺放的石頭從左往右半徑遞增。每次可選擇一塊石頭,並把它放在剩下n-1塊石頭的最左邊或最右邊。求最少操作次數。

輸入描述:

第一行乙個整數n,表示石頭個數(1 <= n <= 100000)。第二行n個整數,表示從左往右石頭的半徑r1,r2,…,rn( 1<= ri <= n)。保證不存在兩個不同的石頭半徑相等。

輸出描述:

最少操作次數。

測試樣例:

63 2 1 4 6 5

輸出:3

問題分析:

本題可轉換為思考求陣列中遞增為1的子串行的最大長度(不必連續)。如樣例中最長的遞增為1的子串行為[3 4 5]。則最少搬運次數為陣列總長度減去最大子串行長度。

題解:

思路一:雙迴圈暴力求解最長的遞增為1的子串行。(會超出時間限制)

n =

int(

input()

)nums =

input()

nums =

[int

(i)for i in nums.split()]

max_len =

1for i in

range

(len

(nums)):

length, num =

1, nums[i]

for j in

range

(i +1,

len(nums)):

if(nums[j]

== num +1)

: num = nums[j]

length +=1if

(length > max_len)

: max_len = length

print

(len

(nums)

- max_len)

思路二:優化時間複雜度,使用動態規劃進行優化。對每個數記錄滿足條件的前面已滿足條件的個數。

狀態方程:dp[i] = dp[nums[i] - 1] + 1。如果dp[nums[i] - 1]存在。

n =

int(

input()

)nums =

input()

nums =

[int

(i)for i in nums.split()]

max_len =

1map_num =

for i in

range

(len

(nums)):

map_num[nums[i]]=

1if(nums[i]-1

in map_num)

: map_num[nums[i]

]= map_num[nums[i]-1

]+1if

(map_num[nums[i]

]> max_len)

: max_len = map_num[nums[i]

]print

(len

(nums)

- max_len)

搬石頭排序

沙灘擺放著一排大小不一的球形石頭,已知第i個石頭的半徑為ri,不存在兩個石頭半徑相等。現要求通過移動石頭使擺放的石頭從左往右半徑遞增。每次可選擇一塊石頭,並把它放在剩下n 1塊石頭的最左邊或最右邊。求最少操作次數。第一行乙個整數n,表示石頭個數。1 n 100000 第二行n個整數,表示從左往右石頭...

陣列排序 計算最少交換次數

交換瓶子 有n個瓶子,編號 1 n,放在架子上。比如有5個瓶子 2 1 3 5 4 要求每次拿起2個瓶子,交換它們的位置。經過若干次後,使得瓶子的序號為 1 2 3 4 5 對於這麼簡單的情況,顯然,至少需要交換2次就可以復位。如果瓶子更多呢?你可以通過程式設計來解決。輸入格式為兩行 第一行 乙個正...

出現次數最少的數

閒來無事,想著把ccf刷到三百分 問題描述 給定n個正整數,找出它們中出現次數最多的數。如果這樣的數有多個,請輸出其中最小的乙個。輸入格式 輸入的第一行只有乙個正整數n 1 n 1000 表示數字的個數。輸入的第二行有n個整數s1,s2,sn 1 si 10000,1 i n 相鄰的數用空格分隔。輸...