題目描述:
沙灘擺放著一排大小不一的球形石頭,已知第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 相鄰的數用空格分隔。輸...