搬石头排序的最少次数

题目描述:
沙滩摆放着一排大小不一的球形石头,已知第i个石头的半径为ri,不存在两个石头半径相等。现要求通过移动石头使摆放的石头从左往右半径递增。每次可选择一块石头,并把它放在剩下n-1块石头的最左边或最右边。求最少操作次数。
输入描述:
第一行一个整数n,表示石头个数(1 <= n <= 100000)。第二行n个整数,表示从左往右石头的半径r1,r2,…,rn( 1<= ri <= n)。保证不存在两个不同的石头半径相等。
输出描述:
最少操作次数。
测试样例:
6
3 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 = 1
for 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 += 1
    if (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 = 1
map_num = {}
for i in range(len(nums)):
    map_num[nums[i]] = 1
    if (nums[i] - 1 in map_num):
        map_num[nums[i]] = map_num[nums[i] - 1] + 1
        if (map_num[nums[i]] > max_len):
            max_len = map_num[nums[i]]

print(len(nums) - max_len)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值