算法学习之路(四)

这篇博客涵盖了多种算法问题,包括峰值元素的线性时间复杂度查找,链表去重的两种方法,以及解决三数之和问题的高效算法。此外,还讨论了含退格字符串的比较和区间列表的交集问题。通过这些实例,深入理解数据结构和算法的应用。
摘要由CSDN通过智能技术生成

1、寻找峰值

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

示例 1:

输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
示例 2:

输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5 
解释:你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6。

class Solution:
    def findPeakElement(self, nums: list[int]) -> int:
        nums.append(-float('inf'))
        low , high = 0 , len(nums) - 1
        while low < high:
            mid = (low + high) // 2
            if nums[mid] < nums[mid + 1]:
                low = mid + 1
            else:
                high = mid 
        return low


if __name__ == '__main__':
    solu = Solution()
    nums = [1,2,3,1]
    print(solu.findPeakElement(nums))

2、删除链表中的重复元素

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

示例 1:
输入:head = [1,1,2]
输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3]
输出:[1,2,3]

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        cur = head
        while cur and cur.next:
            if cur.val == cur.next.val: cur.next = cur.next.next
            else: cur = cur.next
        return head

3、删除链表中的重复元素 2

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]

# 方法一:递归+迭代
from logging import root
class ListNode:
     def __init__(self, val=0, next=None):
         self.val = val
         self.next = next

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not root or not head.next:
            return head
        if head.next != head.next.val :
            head.next = self.deleteDuplicates(head.next)
        else:
            new = head.next
            while new and new.val == head.val :
                new = new.next
            return self.deleteDuplicates(new)
        return head

# 方法二:双指针
"""
①
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        thead = ListNode('a')
        thead.next = head
        pre,cur = None,thead
        while cur:
            pre=cur
            cur=cur.next
            while cur and cur.next and cur.next.val == cur.val:
                t=cur.val
                while cur and cur.val==t:
                    cur=cur.next
            pre.next=cur
        return thead.next
②
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        new = ListNode(0)
        new.next = head
        pre = new 
        cur = head
        while cur:
            if cur.val != cur.next.val:
                pre = cur
                cur = cur.next
            else:
                while cur.next and cur.val == cur.next.val:
                    cur = cur.next
                cur = cur.next
                if not cur or not cur.next or cur.val != cur.next.val :
                    pre.next = cur
                    pre = cur
                    if cur :
                        cur = cur.next
        return new.next
"""

4、三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:

输入:nums = []
输出:[]
示例 3:

输入:nums = [0]
输出:[]

class Solution:
    def threeSum(self, nums: list[int]) -> list[list[int]]:
        n = len(nums)
        res = []
        # 数组为 null 或者数组长度小于 3,返回 []
        if (not nums) or (n < 3):
            return []
        # 对数组进行排序
        nums.sort()
        # 若 nums[0]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回[]
        if (nums[0] > 0):
            return []
        # 遍历排序后数组:
        for i in range(n):
            # 对于重复元素:跳过,避免出现重复解
            if (i > 0 and nums[i] == nums[i - 1]):
                continue
            L = i + 1
            R = n - 1
            # 令左指针 L=i+1,右指针 R=n-1,当 L<R 时,执行循环:
            while (L < R):
                if (nums[i] + nums[L] + nums[R] == 0):
                    res.append([nums[i], nums[L], nums[R]])
                    # 当 nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解
                    while (L < R and nums[L] == nums[L + 1]):
                        L = L + 1
                    while (L < R and nums[R] == nums[R - 1]):
                        R = R - 1
                    # 并同时将 L,R 移到下一位置,寻找新的解
                    L = L + 1
                    R = R - 1
                # 若和大于 0,说明 nums[R] 太大,R 左移
                elif (nums[i] + nums[L] + nums[R] > 0):
                    R = R - 1
                # 若和小于 0,说明 nums[L] 太小,L 右移
                else:
                    L = L + 1
        return res

if __name__ == '__main__':
    solu = Solution()
    nums = [-1,0,1,2,-1,-4]
    print(solu.threeSum(nums))

5、比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。

注意:如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。
示例 2:

输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。
示例 3:

输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。

class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        i = len(s) - 1
        j = len(t) - 1
        num_s = num_t = 0
        while i >= 0 or j >= 0:
            while i >= 0:
                if s[i] == "#":
                    num_s += 1
                    i -= 1
                elif num_s > 0:
                    num_s -= 1
                    i -= 1
                else:
                    break

            while j >= 0:
                if t[j] == "#":
                    num_t += 1
                    j -= 1
                elif num_t > 0:
                    num_t -= 1
                    j -=1
                else:
                    break
            if i >= 0 and j >= 0:
                if s[i] != t[j]:
                    return False
            elif i >= 0 or j >= 0:
                return False
            """
                        s = "" if i < 0 else S[i]
                        t = "" if j < 0 else T[j]
                        if s != t:
                            return False
            """
            i -= 1
            j -= 1
        return True






if __name__ == '__main__':
    solu = Solution()
    s = "a#c"
    t = "#b"
    print(solu.backspaceCompare(s,t))

6、区间列表的交集

给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。

返回这 两个区间列表的交集 。

形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。

两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。

示例 1:


输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
示例 2:

输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]
示例 3:

输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]
示例 4:

输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]

# 方法一 :双指针
class Solution:
    def intervalIntersection(self, firstList: list[list[int]], secondList: list[list[int]]) -> list[list[int]]:
        ans = []
        f, s = firstList, secondList
        L, R = 0, 0
        while L < len(firstList) and R < len(secondList):
            if s[R][0] > f[L][-1]:     #区间不重合且L更小
                L += 1
            elif f[L][0] > s[R][-1]:   #区间不重合且R更小
                R += 1
            else:
                if f[L][0] <= s[R][0]:
                    if f[L][1] >= s[R][1]:    #情况1
                        ans.append([s[R][0], s[R][1]])
                        R += 1
                    elif f[L][1] <= s[R][1]:  #情况2
                        ans.append([s[R][0], f[L][1]])
                        if f[L][1] == s[R][1]:
                            L += 1
                            R += 1
                        else:
                            L += 1
                    elif f[L][1] == s[R][0]:  #情况3
                        ans.append([s[R][0], s[R][0]])
                        L += 1

                else:
                    if f[L][1] >= s[R][1]:    #情况1
                        ans.append([f[L][0], s[R][1]])
                        R += 1
                    elif f[L][1] <= s[R][1]:  #情况2
                        ans.append([f[L][0], f[L][1]])
                        if f[L][1] == s[R][1]:
                            L += 1
                            R += 1
                        else:
                            L += 1
                    elif f[L][0] == s[R][1]:  #情况3
                        ans.append([f[L][0], f[L][0]])
                        L += 1
        return ans

"""
方法二:pop
"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值