leetcode刷题日记

除了算法题 可能没有让人更开心的了
从今天起,每天两个算法题呀

两数之和

题目链接:https://leetcode-cn.com/problems/two-sum
在这里插入图片描述
我的解法:
因为没有什么哈希表的知识,刚开始重拾算法题,已经回到铁憨憨的状态了。所以写了一个平时的工程的解法,

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i in range(0, len(nums) ):
            for j in range(i + 1, len(nums)):
                if nums[i] + nums[j] == target:
                    return[i,j]

这个程序的运行的时间全凭在数组中的位置决定了。
也想过如何简化,如排序一下,如果和比较小,那些大于他的可以被丢掉了。
大佬们的解法都是哈希表。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap = {}
        for idx, num in enumerate(nums):
            if target - num in hashmap:
                return [hashmap[target - num],idx]
            else:
                hashmap[num] = idx

只出现一次的数字

题目链接:https://leetcode-cn.com/problems/single-number/
题干
要求是非空整数数组,且某个元素只出现一次,并找出他。
要求 线性时间复杂度,且不使用额外空间
最近都用的python,选择的python2 的编辑器(python3的没太看懂)
我的解法:

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
    
        for i in nums:
            if nums.count(i)==1:
                return i

利用了列表的自带函数计数功能,自己计算为一次的,
算是个投机取巧吧。

在解题区看到了很多的大佬解法:

  1. 使用了异或
    大佬用遍历数组,并使用异或相加,和自己的异或相当于0,最后剩下的数字就是唯一的数字。在这里插入图片描述
 for i in nums:
            a ^= i
        return a
  1. 数学解法
    2∗(a+b+c)−(a+a+b+b+c)=c
    把列表编程集合,然后✖️2,减去列表的值 的和
return 2 * sum(set(nums)) - sum(nums)
  1. 哈希表
    我们用哈希表避免每次查找元素是否存在需要的 O(n)O(n) 时间。

遍历 nums 中的每一个元素
查找 hash_table 中是否有当前元素的键
如果没有,将当前元素作为键插入 hash_table
最后, hash_table 中仅有一个元素,用 popitem 获得它

多数元素

题目链接:https://leetcode-cn.com/problems/majority-element/
在这里插入图片描述
此题目 超过了70% 的代码。还可以。

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        
        value = int(len(nums)/2)
        for i in set(nums):
            if nums.count(i)>value:
                return i
        

这种计数问题,可以确定的是,超过半数的数字一定有且只有一个。所以在计数过程中如果出现了超过半数的数字,我们可以立刻返回。
我的想法是,将列表转化为字典,然后对字典里的值依次求次数,发现超过半数的值,就返回。

  1. 摩尔投票法:
    在这里插入图片描述
    也是一种数学的想法,读了很多遍才想明白。

2.api方法
使用 排序的方法,将列表排序,然后返回列表中中间位置的数字。

Arrays.sort(nums);
return nums[nums.length / 2]; 

合并两个有序数组

在这里插入图片描述

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        item = 0
        length = m

        if m==0:
            for i in range(0,len(nums2)):
                nums1[i] = nums2[i]
        else:
            for i in nums2:
                for j in range(item,length):

                    if i > nums1[length-1]:

                        nums1.insert(length, i)
                        nums1.pop(-1)
                        length = length + 1
                        item = j + 1
                        break
                    if i <=nums1[j]:
                        nums1.insert(j , i)
                        nums1.pop(-1)

                        length = length + 1
                        item = j + 1
                        break
                    elif i > nums1[j]:
                        if i <= nums1[j+1]:

                            nums1.insert(j+1,i)
                            nums1.pop(-1)
                            length = length +1
                            item = j+1
                            #print(item)
                            break

这个代码居然打败了99%的人的算法运行速度。但是其实并不好。因为占的空间多。我的想法就是,遍历第二个数组将其和第一个数组的元素挨个比较,插入并删除最后面的那个0。

  • 小于某个值,就插入在当前位置
  • 大于值a,小于值a的下一个,就插入在a的后面,
  • 如果大于列表1最大值,直接插入列表一最后一个值得后面。
    过程中发现,列表1 会有为空的情况,还额外写了一个判断来避免这种情况。
    看题解的话,就是惊呆了。

方法一 : 合并后排序
最朴素的解法就是将两个数组合并之后,再排序。
将数组2替换数组1的0的值,
这种方法的时间复杂度较差,为O((n + m)\log(n + m))O((n+m)log(n+m))。这是由于这种方法没有利用两个数组本身已经有序这一点。

方法二: 双指针 / 从后往前在这里插入图片描述
确实比我的方法高明了不少

搜索二维矩阵 II

链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/
在这里插入图片描述
因为昨天学习了指针 今天也想学高端解法 最终也没发现什么数学解法。
写的解题方案也不是特别的高明。就不放上来。

因为矩阵的行和列是排序的(分别从左到右和从上到下),所以在查看任何特定值时,我们可以修剪O(m)或O(n)元素。

算法:
首先,我们初始化一个指向矩阵左下角的 (row,col) 指针。然后,直到找到目标并返回 true(或者指针指向矩阵维度之外的 (row,col)为止,我们执行以下操作:如果当前指向的值大于目标值,则可以 “向上” 移动一行。 否则,如果当前指向的值小于目标值,则可以移动一列。不难理解为什么这样做永远不会删减正确的答案;因为行是从左到右排序的,所以我们知道当前值右侧的每个值都较大。 因此,如果当前值已经大于目标值,我们知道它右边的每个值会比较大。也可以对列进行非常类似的论证,因此这种搜索方式将始终在矩阵中找到目标(如果存在)。

验证回文串

在这里插入图片描述

class Solution(object):
    def isPalindrome(self, s):
        """
        :type s: str
        :rtype: bool
        """
        import re
        new = re.findall("[0-9A-Za-z]",s)
        length = int(len(new)/2)
        flag = True
        for i in range(0,length):
            if new[i].upper() == new[len(new)-1-i].upper():
                pass
            else:
                flag=False
        return flag

今天这道题,本来看起来不是很难,但是自己真心想了半天 不会做。知道要用递归来解答,但是有种无从下手的感觉。
因为之前没有接触过这种问题,这次好好学习。
希望下一次就可以解答出来了吧!

网上给出的解答方式为:回溯法

回溯法的核心思想就是递归,虽然其过程逻辑很清楚,而且执行效率很高。但缺点也是与之对应的,逻辑清楚,必然其抽象性很高,所以有时候就是这样的情况:看它的解题过程很容易看懂,但要是让你自己动手写这个递归过程,发现很难下笔。

描述:

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

其实总结起来就3点:

1 出口。
一个递归算法一定要有出口,否则就是一个死循环了。出口语句一般都挺好写的,但 是出口语句该放在哪儿了,这个就是关键了。
这个语句其实挺好写的,一般也就2-3行代码,大多数人都能想出来。但大多数人苦恼的就是不知道该把它放在哪儿,把出口语句放在递归函数的第一行就行。

2 递归函数的参数。
一般情况下,递归函数是要带参数的,因为递归操作都是用来处理下一次的过程,如果没有参数的话,那么就很难从下一次的操作回溯到当前操作了。
这个递归函数的参数的设置也是有很大门道的,设置的好就很容易得到答案,否则弄大半天可能还是没有一点反应。大家一定要记住一点:这个参数是随着每一次的递归操作而发生改变的。而回溯法很关键的一点就是:如果当前操作行不通,如何回溯到上一步操作。大家继续看上面贴的两个递归函数的参数,会发现其参数都是要改变的,既然参数会发生改变,那么我们要如何保存其上一步操作的值呢?

结果一定是要有一个全局参数来保存,这个全局参数不会随着每一次的递归操作而随时改变,它只是用来保存每一次递归操作成功时的结果,其它的不关它的事。在一开始就定义了一个List空列表。大家也可以照搬的,凡是结果需要保存的题目90%以上就是要预先定义一个List空列表

3 递归函数的处理过程。
这个自不必多说,重中之重,需要好好理解其过程

如果当前递归过程的处理参数符合要求,则执行相关赋值或其它操作,然后转入下一次递归,如果下一次递归不能找到出口,则把之前相关赋值或其它操作重置为初始状态。

加一

题目链接:https://leetcode-cn.com/problems/plus-one/
在这里插入图片描述

没什么难度
看评论很多人没看懂题目。然后需要考虑很大的数字的情况,内存溢出问题。我没想过*10去算,毕竟加1就行了。
我的解法:

class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        value = ''
        for i in digits:
            value = value+str(i)

        aList= []
        for i in str(int(value)+1):
            aList.append(int(i))
        return aList

就是先把列表转化为数字,在把数字转化为列表。
在这里插入图片描述
在这里插入图片描述

存在重复元素

网页链接:https://leetcode-cn.com/problems/contains-duplicate/
在这里插入图片描述
我的解法使用了字典,把他变成了字典,然后比较长度即可。

class Solution(object):
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        set_=set(nums)
        list_ = list(set_)
        if len(nums) == len(list_):
            return False
        else :
            return True

在这里插入图片描述

字符串中的第一个唯一字符

题目链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string/
在这里插入图片描述

看了大神的解法表示 再简单的题,大神也能写出花来。

整数反转

在这里插入图片描述

外观数列

一遍过 太不容易了
看评论区一堆人抖机灵的回答~
我的想法比较 普通,就是有一个count 一个num,比较下一位和当前值的区别,如果相同的话就加count,不同的话就变num和str。

def countAndSay(n):
    """
    :type n: int
    :rtype: str
    """
    n_list = ['1']
    for i in range(0,n):
        if len(n_list)<i+1:
            print(i+1,n_list[-1])
            flag = False
            while flag!=True:
                #print(n_list[-1][:])
                num = n_list[-1][0]
                count = 1
                strn = ''
                for item in range(1,len(n_list[-1])):
                    print(n_list[-1][item])

                    if num==n_list[-1][item]:
                        count +=1
                    else:
                        strn = strn+str(count)+str(num)
                        num = n_list[-1][item]
                        count = 1
                strn = strn + str(count) + str(num)
                n_list.append(strn)
                break
    return n_list[-1]

print(countAndSay(5))

买卖股票的最佳时期

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
在这里插入图片描述

def maxProfit( prices):
    """
    :type prices: List[int]
    :rtype: int
    """
    num =prices[0]
    profit = 0
    for i in range(1,len(prices)):
        #print(prices[i],num)
        if prices[i] > num:
            profit = prices[i] - num +profit
            num = prices[i]
        else:
            num = prices[i]
    return profit
print(maxProfit([1,2,3,4,5]))

题目比较简单 懒得思考 没有优化代码
在这里插入图片描述

反转字符串

链接:https://leetcode-cn.com/problems/reverse-string/
在这里插入图片描述
没什么难度,就是不可以使用return。
必须真正修改原先的列表
所以为了减少时间复杂度,遍历字符串长度一半,进行头尾的数字交换即可。
注意,需要用一个临时变量来存储其中的值。

字符串转换整数 (atoi)

题目链接:https://leetcode-cn.com/problems/string-to-integer-atoi/
在这里插入图片描述

这道题的难度居然算是中等,我认为这个是真的烦
没啥意思
他有很多隐藏的内容,得测试的时候才发现有问题。
比如 ±2 是错误的,返回0
比如 +2 0,会返回2…… 需要实际试错

我的想法非常的复杂。。也懒得简化了

class Solution(object):
    def digit(self, i):
        num = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
        if i in num:
            return True
        return False

    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        value = ''
        # str = str.replace(" ", "")
        flag = True
        if len(str.replace(" ", ""))==0 or len(str) == 0:
            return 0
        elif len(str) == 1 and self.digit(str[0]) == True:
            return int(str) #就一个数字
        elif len(str) == 1 and self.digit(str[0]) == False:
            return 0
        newStr = ""
        space = False

        for i in range(0,len(str)):
            if str[i] == " ":
                if space == True:
                    break

            else:
                newStr = newStr + str[i]
                space = True
        str = newStr
        if self.digit(str[0]) == False and str[0] != "-" and str[0] != "+":
            return 0
        elif str[0] == '-':
            value = value + '-'
            for i in range(1, len(str)):
                if flag:
                    if self.digit(str[i]):
                        value = value + str[i]
                    else:
                        flag = False
        elif str[0] == '+':
            for i in range(1, len(str)):
                if flag:
                    if self.digit(str[i]):
                        value = value + str[i]
                    else:
                        flag = False
        else:
            for i in range(0, len(str)):
                if flag:
                    if self.digit(str[i]):
                        value = value + str[i]
                    else:
                        flag = False
        print(value)
        if len(value) <= 1 and self.digit(value)==False:
            return 0
        else:
            num = int(value)

        if num > 2147483648:
            return 2147483648
        elif num < -2147483648:
            return -2147483648
        else:
            return num

a = Solution()
print(a.myAtoi("    "))

我的想法确实比较复杂,看了一下大佬的解法。确实简单了一点点。相差无几。
但是确实这种题正则表达式就是一行的事情。

class Solution:
    def myAtoi(self, s: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)

两个数的交集

题目链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值