算法刷题——双指针(1)

自从昨天结束数模校赛和概率论期中考试之后,发现突然一下子闲下来了呢。虽然虽然还有很多想学的知识没有学,但是一不小心惫懒的情绪就从心底蔓延开了。

咳咳咳,言归正传,今天学习的算法还是双指针。通过刷题我也发现了双指针是真的强大,在一些题目中使用双指针的话,往往可以把时间复杂度降为O(n),空间复杂度也只是O(1)级别的。

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-string

示例 1:

输入:hello
输出:["o","l","l","e","h"]

这道题比较简单,可以使用的方法有很多,比如冒泡排序等。当然,最简单的做法还是双指针。初始化指针i指向数组首元素,指针j指向数组尾元素,然后交换两个指针所指的元素,然后指针i后移一位,指针j前移一位,重复前面的做法,直到指针i >= j。 

s = list(input())
n = len(s)
i = 0
j = n-1
while i < j:
    s[i],s[j] = s[j],s[i]
    i += 1
    j -= 1
print(s)

 

 

输入一个长度为 n 的整数数组 height,元素用空格分开 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/container-with-most-water

 

示例 1:

算法刷题——双指针(1)_第1张图片

 

输入:1 8 6 2 5 4 8 3 7
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

 他们都说这道题有点难,其实嘞,就是方法有些难想。确实一般做题不多的人很难想到用双指针来解决这道题。然后因为我是在双指针专栏里面做这道题的,所以一直往双指针方面想,做出来的还比较快。

这里我们因为要使“容器”能够尽可能的多盛水,而盛水的多少与“容器”的底还有高有关。所以开始时我们首先使“容器”的底最大,即让指针i指向第一个元素,指针j指向最后一个元素,并求出此时构成“容器”能够盛水的ans。然后逐步缩小“容器”的底。因为让指针i后移和指针j前移的后果一样(都是让底变成了j-i-1),而为了使新“容器”尽可能盛更多的水,于是将指针i指向的元素和指针j指向的元素进行比较,并选择将指向元素较小的那个指针进行移动(如果相同,那就随便移动一个指针),计算此时新“容器”的最大盛水量,并于ans比较,对ans进行更新。重复这项操作,直到i >= j。输出ans

height = list(map(int,input().split(' ')))
n = len(height)
i = 0
j = n-1
ans = (j-i)*min(height[i],height[j])
while i < j:
    if height[i] < height[j]:
        i += 1
        ans = max(ans,(j-i)*min(height[i],height[j]))
    else:
        j -= 1
        ans = max(ans,(j-i)*min(height[i],height[j]))
print(ans)

 

输入 n 个非负整数(每个整数用空格分开)表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水 (力扣42,接雨水)

示例 1:算法刷题——双指针(1)_第2张图片

 

输入:0 1 0 2 1 0 1 3 2 1 2 1
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)

来源:力扣(LeetCode)

终于终于在力扣上做出来了一道困难级别的题(勉强算是做出来了吧,测试样例跑了308/312,最后因为运行超时了,所以没有成功,看来python还是运行代码太慢了,下次把代码改成c应该就行了吧)

这道题的思路和上个月蓝桥杯最后一道题“最优清零方案”相似(比赛时也没做出来那道题,还是前几天重新看题时想出来的思路),都是一层一层的单独考虑。

对于第i层,首先使指针j指向第一个大于等于i的元素 指针k从第j+1个元素开始遍历,若指针k指向的元素大于等于i,则计算该层第j个元素到第k个元素能够接到的雨水量k-j-1,并将指针j移动到指针k指向的元素,指针k继续向后移动。重复操作,直到k遍历所有元素,得到该层能够接到的雨水量,将所有层能够接到的雨水量相加,即为最终答案。

height = list(map(int,input().split(' ')))
l = len(height)
Max = max(height)
ans = 0
lo = 0 #记录第i层第一个大于等于i的元素的位置,当计算第i+1层时,可以直接从这个位置开始找大于等于i+1的元素
for i in range(1,Max+1):
    for j in range(lo,l):#寻找第一个大于等于i的元素的位置
        if height[j] >= i:
            break
    lo = j
    for k in range(j+1,l):#计算该层能够接到雨水的数量
        if height[k] >= i:
            ans += k-j-1
            j = k
print(ans)

 ps:因为力扣中的题目都不需要输入,所以我对题目稍稍做了一下改变。

今天又是充实的一天,明天继续加油!!!

 算法刷题——双指针(1)_第3张图片

 

你可能感兴趣的:(算法)