zoukankan      html  css  js  c++  java
  • Leetcode之two pointers(前200道)

    持续更新。。

    github:https://github.com/x2mercy/Leetcode_Solution

    一种和数组经常一起出现的算法,虽然很简单,但我觉得还是需要mark一下,因为有的时候用这种算法可以避免多层循环,避免了很多重复,复杂度大大降低。

    EASY:

    其实在做easy前面几道题的时候,只注意到是array的题目,并没有太注意到这是一种很便捷的题目,毕竟刚开始的题目比较简单。

    到后来,开始刷medium的题的时候,才发现这样的做法是多么的便捷,而且有的时候不这么做的话,会报time limie exceed的错(捂脸)

    这里面的有些『做后感』是当时刷完在github里随便写的.md文件,所以刚开始的『做后感』有点弱智哈哈哈

    1. Remove Duplicates from Sorted Array:

    Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length.

    Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

    class Solution(object):
        def removeDuplicates(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if not nums:
                return 0
            j=0
            for i in range (len(nums)):
                if nums[i]!=nums[j]:
                    j+=1
                    nums[j]=nums[i]
            return j+1
    本来想从第一个元素开始,挨个比较,然后用del操作删掉重复的元素,但是定义nums[i+1]会报错:list index out of range,
    题目又说不可以allocate另外一个列表来做,所以定义j来作为另一个pointer,如果num[i]!=num[j],则j+1,将num[i]的值赋给num[j],
    如果相等,则继续i+1比较下一个元素,这样最后将j+1就是len

    2. Remove Element:

    Given an array and a value, remove all instances of that value in-place and return the new length.

    Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

    The order of elements can be changed. It doesn't matter what you leave beyond the new length.

    class Solution(object):
        def removeElement(self, nums, val):
            """
            :type nums: List[int]
            :type val: int
            :rtype: int
            """
            j=0
            if not nums:
                return 0
            for i in range(len(nums)):
                if nums[i]!=val:
                    nums[j]=nums[i]
                    j=j+1
            return j
    这道题刚开始按照上一题的做法做,发现会报错,因为j一开始为0,所以j[0]会被读出,所以调换了j+1和num[j]=num[i]的顺序
    3. Valid Palindrome:

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

    For example,
    "A man, a plan, a canal: Panama" is a palindrome.
    "race a car" is not a palindrome.

    Note:
    Have you consider that the string might be empty? This is a good question to ask during an interview.

    For the purpose of this problem, we define empty string as valid palindrome.

    class Solution(object):
        import string
        def isPalindrome(self, s):
            """
            :type s: str
            :rtype: bool
            """
            l=0
            r=len(s)-1
            while l<r:
                while not s[l].isalnum() and l<r:
                    l+=1
                while not s[r].isalnum() and l<r:
                    r-=1
                if s[l].lower()!=s[r].lower():
                    return False
                l+=1
                r-=1
            return True
                

    回文的题目,用two pointers做是最快最准的!这样是很经典的一种two pointer算法,即指针分别从string两段向中间靠近,所以循环的条件就是l<r

    大循环里面小循环用来排除不是字母和数字的字符,用的是.isalnum()。最后无条件l+=1,r+=1

    4. Linked List Cycle:

    Given a linked list, determine if it has a cycle in it.

     这道题一定要Mark一下!

    # Definition for singly-linked list.
    # class ListNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution(object):
        def hasCycle(self, head):
            """
            :type head: ListNode
            :rtype: bool
            """
            try:
                slow=head
                fast=head.next
                while slow is not fast:
                    slow=slow.next
                    fast=fast.next.next
                return True
            except:
                return False
                
                
            

    这道题是寻找一个链表里有没有循环。快指针每次.next.next,慢指针.next,用了try...except,如果是有cycle的话,慢指针和快指针总会遇到,于是返回true。

    如果没有(except),返回false

    如下图:

    5. Two Sum II - Input array is sorted:

    Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

    The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

    You may assume that each input would have exactly one solution and you may not use the same element twice.

    Input: numbers={2, 7, 11, 15}, target=9
    Output: index1=1, index2=2

    class Solution(object):
        def twoSum(self, numbers, target):
            """
            :type numbers: List[int]
            :type target: int
            :rtype: List[int]
            """
            l=0
            r=len(numbers)-1
            while l<r:
                sum_num=numbers[l]+numbers[r]
                if sum_num==target:
                    return [l+1,r+1]
                elif sum_num<target:
                    l+=1
                elif sum_num>target:
                    r-=1

    左右两个pointers,条件是l<r,然后循环的最后是有条件的l+=1或者r-=1,取决于sum_num是否小于target,因为array是已经排好的,所以如果比target大,证明要让sum_num变小

    所以右指针向左移

    MEDIUM

    1. Longest Substring Without Repeating Characters:

    Given a string, find the length of the longest substring without repeating characters.

    Examples:

    Given "abcabcbb", the answer is "abc", which the length is 3.

    Given "bbbbb", the answer is "b", with the length of 1.

    Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequenceand not a substring.

    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            if s=="":
                return 0
            if len(s)==1:
                return 1
            start=0
            max_s=0
            nums={}
            for i in range(len(s)):
                if s[i] in nums and start<=nums[s[i]]:  
                    start=nums[s[i]]+1
                else:
                    nums[s[i]]=i
                    max_s=max(max_s,i-start+1)
                nums[s[i]]=i
            
            return max_s
    这道题反映了我coding的一个缺点,我的逻辑太直了,不会去利用index和添加另一个指针来做题,导致刚开始写出来的都是if if if
    这样是不行的,要注意
    其实这道题很简单,related topic也给了提示,要用dictionary做。
    但是一开始我想错了,我用字典的值存放个数,这样是不对的。
    看了discuss之后,发现,原来最机智的做法是用字典的值存放Index,这样可以利用一个指针start来作为『慢指针』
    这样的好处在于,只有当字典里存放过的元素出现了的时候(即重复的元素),start才会从重复元素的第一个元素的Index+1开始,
    即,从重复元素的第一个元素后一个元素开始比较,这样在计算长度的时候可以从这个start开始计算
    如果当s[i]不是重复元素时,比较用目前无重复元素的长度和之前的max做比较,较大的赋给max_s
    每次循环的最后,照例把当前元素和其Index存入字典

    2. Container With Most Water:

    Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

    Note: You may not slant the container and n is at least 2.

    class Solution(object):
        def maxArea(self, height):
            """
            :type height: List[int]
            :rtype: int
            """
            max_area=0
            current_area=0
            l=0
            r=len(height)-1
            while l<r:
                max_area=max(max_area,(r-l)*min(height[l],height[r]))
                if height[l]<height[r]:
                    l+=1
                else:
                    r-=1
            return max_area
                

    这道题就是第一次尝试用了两层循环,然后超时,改用两个指针

    left+1和right-1的条件分别是:如果height[left]和height[right]哪个小,left小就+1,right小就-1

    3. 3Sum

    Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

    Note: The solution set must not contain duplicate triplets.

    solution1: 没跑过checker 原因是找出的所有list必须按照原List的排列顺序排(可是题目也没说呀气气)

    import copy
    class Solution(object):
        def threeSum(self,nums):
            result=[]
            i=0
            zero=[]
            if nums.count(0)>=3:
                zero=[0,0,0]
                result.append(zero)
            for i in range(len(nums)):   
                zero=[]
                for j in range(i+1,len(nums)):
                    nums_copy=copy.deepcopy(nums)
                    if -(nums[i]+nums[j]) in nums:
                        one=nums[i]
                        nums_copy.remove(one)
                        two=nums[j]
                        nums_copy.remove(two)
                        if not -(one+two) in nums_copy:
                            break
                        three=-(nums[i]+nums[j])
                        zero.append(one)
                        zero.append(two)
                        zero.append(three)
                        tag=0
                        for n in range(len(result)):
                            flag=0
                            for m in range(len(zero)):
                                if zero[m] in result[n]:
                                    flag+=1
                            if flag==3:
                                break
                            else:
                                tag+=1
                                continue
                        if tag==len(result):
                            result.append(zero)
                        zero=[]
                        
            return result

    solution2: two pointers

    class Solution(object):
        def threeSum(self,nums):
            nums.sort()
            result=[]
            for i in range(len(nums)-2):
                zero=[]
                if i > 0 and nums[i] == nums[i-1]:
                    continue
                l, r = i+1, len(nums)-1
                while l<r:
                    zero=[]
                    s=nums[i]+nums[l]+nums[r]
                    if s<0:
                        l+=1
                    elif s>0:
                        r-=1
                    else:
                        zero.append(nums[i])
                        zero.append(nums[l])
                        zero.append(nums[r])
                        result.append(zero)
                        while l<r and nums[l]==nums[l+1]:
                            l+=1
                        while l<r and nums[r]==nums[r-1]:
                            r-=1
                        l+=1
                        r-=1
            return result

    先sort,主要是有一个i一直+1,然后l=i+1,r=len(nums)-1,从两边加减    然后相加如果小于0,则l+1,如果大于0,r-1    需要注意的是!要避免重复!在循环的开始,要比较nums[i]和nums[i-1]的大小,如果是一样的,就要continue,不然会重复。在循环的最后,要看一下nums[l]是否等于nums[l+1]以及nums[r]是否等于nums[r+1],因为如果相等的话,再进行l+1和r+1的操作,又会重复

    4. 3Sum Closest:

    Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    class Solution(object):
        def threeSumClosest(self, nums, target):
            """
            :type nums: List[int]
            :type target: int
            :rtype: int
            """
            nums.sort()
            result=nums[0]+nums[1]+nums[2]
            for i in range(len(nums)-2):
                l=i+1
                r=len(nums)-1
                while l<r:
                    s=nums[i]+nums[l]+nums[r]
                    if s==target:
                        return s
                    if abs(target-s)<abs(target-result):
                        result=s
                    if s<target:
                        l+=1
                    elif s>target:
                        r-=1
            return result
                
                
                
                

    这道题一开始没想通怎么用two pointers做,因为不知道拿什么去比较,一开始想的超简单,耍了小聪明,以为把target先存入array,然后sort,然后target附近的几个数加起来就是最接近target的数,可是没有考虑到有负数的存在。所以还是重新用two pointers做,先把前三个数相加,作为一个『标准』,然后和3sum一样,i从0-len(nums)-2(-2是因为有l,r),然后l从i+1开始,r从len(nums)-1开始像中间靠拢,然后比较target-s和target-result,并把小的那个赋给result,要注意的是,要用绝对值!然后如果target-s比target-result大,所以需要被fix,fix条件就是比target大还是小,如果大的话,r-,如果小的话l+,总之就是像target靠近 

  • 相关阅读:
    C#关机代码实例详解
    如何设计通用的网站模板
    C# XML解析方式实例解析1
    ASP.NET配置错误页面浅析
    几种常用的C#排序方法简介
    简述C# XML解析方法的特点及应用
    请不要相信
    浅谈ASP.NET Forms验证
    设计友好的错误信息页面
    详解.NET中容易混淆的委托与接口
  • 原文地址:https://www.cnblogs.com/x1mercy/p/7837145.html
Copyright © 2011-2022 走看看