题目就不描述啦,leetcode的题。这题应该蛮好想到思路。一般只有题目有最长的字眼都是动态规划求解。
动态规划在思考时有两个从选与不选下手。不选很简单,不选就是dp[i]= dp[i-1],选呢?
选的关键在于,找到前序序列中满足条件要求的前序序列。
依次遍历0~i-1,如果满足条件nums[i] > nums[j],那么更新dp[i] = dp[j] + 1。注意!!这种结果是错误的!!!
以 [12,22,4,32] 为例,因为每次只要满足条件,32>12,32>22,32>4,那么dp[i]都更新,所以最后更新的是dp[i-1],也就是4的dp的值1再加1.很显然,这个最长子串的长度为3【12,22,32】
因此,还要满足一个条件,dp[j] + 1 >= dp[i]
:时才更新。
若输入为:nums = [12,22,4,32,7,8,2,3,18]
输出:dp = [1, 2, 1, 3, 2, 3, 1, 2, 4]
注意,最长子串至少应该是一个不减的结果。如果在每次更新dp[i]时修改dp[i]为前面的最大值,也会出现错误。
如 对于4,前面的最大值为2,即【12,22】,当考虑到7时,7大于4,因此更新7为dp[4的位置] +1.这句话是说,我们当前找到的序列是[12,22,7]!!!这样是错误的!
那怎么找到最长呢?把dp每个位置取之前的max即可。
详细的解答可以看网上答案或者最后付的代码~
——————————————————————————————————————————————————————
分割线!!!
朋友在字节的面试时,出了类似的题目,但引申为返回最长元素的下标。她说当时动态规划没想到,用暴力法解的。我现在暴力法还没想到,等写出来会更新。
我思考了一下,动态规划应该也是能做的。就是添加一个记录每个位置的字符串就够了。我用的是字典,键为位置,值为此位置下的最长字符串,代码如下:
def findmaxlength(nums):
dp = [1]*len(nums)
dict={}
dict[0] = [nums[0]]
ans = [1]*len(nums) #存当前位置最长的
re = {} #存最后返回的元素
re[0] = [nums[0]]
for i in range(1,len(nums)):
dict[i] = [nums[i]] #初始化
for j in range(i):
if nums[i] > nums[j]: #dp[i]=max(dp[i],dp[j]+1)
if dp[j] + 1 >= dp[i]:
dp[i] = dp[j] + 1
tmp = dict[j][:]
tmp.append(nums[i])
dict[i] = tmp[:]
#都没有的话,dict[i]应该为最大值
maxindex = 0
for k in range(i+1):
if dp[k] > dp[maxindex]:
maxindex = k
ans[i] = dp[maxindex]
re[i] = dict[maxindex]
print(dp)
print(ans)
print(dict)
return re
if __name__ == "__main__":
nums = [12,22,4,32,7,8,2,3,18]
print(findmaxlength(nums))
结果:
[1, 2, 1, 3, 2, 3, 1, 2, 4]
[1, 2, 2, 3, 3, 3, 3, 3, 4]
{0: [12], 1: [12, 22], 2: [4], 3: [12, 22, 32], 4: [4, 7], 5: [4, 7, 8], 6: [2], 7: [2, 3], 8: [4, 7, 8, 18]}
{0: [12], 1: [12, 22], 2: [12, 22], 3: [12, 22, 32], 4: [12, 22, 32], 5: [12, 22, 32], 6: [12, 22, 32], 7: [12, 22, 32], 8: [4, 7, 8, 18]}
————————————————————————————————
更新:暴力解法
暴力解法的思路就是,找到以每个数字打头的所有满足条件的子串,然后再从里面找最大。以【12,3,32,4,7,8,2】为例,如果是找3的话,就是3打头,以32,4,7,8,2依次作为第二个元素,一直向下找。
朋友说字节的题是要递增1,只要把条件改成相差1即可。最后的代码为:
def findmaxlength(nums):
#思路:找从每个下标开始所有可能的数组
ans = [1]*len(nums)
maxlen = 1
ans = []
for i in range(len(nums)):
for j in range(i+1,len(nums)): #第j个元素依次作为第二个元素
if nums[j] - nums[i] == 1:
tmp = [nums[i],nums[j]]
for k in range(j+1,len(nums)):
if nums[k] - tmp[-1] == 1:
tmp.append(nums[k])
if len(tmp) >maxlen:
ans = tmp[:]
maxlen = len(tmp)
print(ans)
return maxlen
测试:nums = [9,1,2,7,3,4,5,8]
输出:
[1, 2, 3, 4, 5]
5