[leetcode]初级算法——数组

本文详细探讨了多个LeetCode数组相关的算法问题,包括买卖股票的最佳时机 II、旋转数组、存在重复元素、只出现一次的数字、两个数组的交集 II、加一、移动零、两数之和以及旋转图像。通过代码实现和总结,阐述了解决这些问题的不同方法和思路。
摘要由CSDN通过智能技术生成

买卖股票的最佳时机 II 

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).


Example:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Code(By myself):

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices) < 2:
            return 0
        buy = 0
        sell = 0
        profit = 0
        while sell < len(prices) - 1:
            while sell < len(prices) - 1 and prices[sell] < prices[sell + 1]:
                sell += 1
            if sell != buy:
                profit = profit + prices[sell] - prices[buy]
                buy = sell + 1
                sell = buy
            if sell < len(prices) - 1 and prices[sell] >= prices[sell + 1]:
                sell += 1
                buy += 1
            
        return profit

Code(Others):

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        profit = 0
        for i in range(1,len(prices)):
            if prices[i] > prices[i-1]:
                profit += prices[i]-prices[i-1]
        return profit

总结:

经观察,若处于升序,则在升序第一元素买入,最后一个元素出售,故设两个指针sell和buy。升序买入卖出,profit=buy-sell;降序跳过。

不足:

  1. 未能考虑到profit可以等于升序数列中相邻元素之差再求和即可;
  2. 由于1导致sell本质是多余指针,可删除          

旋转数组

Rotate an array of n elements to the right by k steps.

For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].

Note:

Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.

Could you do it in-place with O(1) extra space?

Example:

输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

Code(By myself):

伪代码:
reverse(nums,0,len(nums)-1)
reverse(nums,0,k%len(nums)-1)
reverse(nums,k%len(nums),len(nums)-1)
python:
class Solution:
            
    def reverse(self,nums,left,right):
        while right > left:
            value = nums[left]
            nums[left] = nums[right]
            nums[right] = value
            left += 1
            right -=1
            
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        self.reverse(nums,0,len(nums)-1)
        self.reverse(nums,0,k%len(nums)-1)
        self.reverse(nums,k%len(nums),len(nums)-1)

Code(Others):

class Solution:
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        i = k % length
        nums[:] = nums[-i:]+nums[:-i]

总结:

  1. list[a:b]表示从第a个元素到第b个元素,list[-i:]表示列表倒数i个元素,list[:-i]表示列表倒数第i个元素之前所有元素
  2. leetcode调用函数应用self.函数名调用

存在重复元素

Given an array of integers, find if the array contains any duplicates.

Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

Example:

Input: [1,2,3,1]
Output: true

Code(By myself):

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

Code(Others):

class Solution:
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        
        #把列表转化为集合,因为集合里的元素是唯一的,所以可以通过看转化后长度是否发生改变来判断。测试通过,效率最高
        return True if len(nums)!=len(set(nums)) else False
    
        
        """
        # 双循环。测试超时
        for i in range(len(nums)-1):
            for j in range(i+1, len(nums)):
                if nums[i]==nums[j]:
                    return True
        return False
      
      
        #先排序,再进行前后比较。测试通过
        nums.sort()
        if len(nums)==1:
            return False
        for i in range(len(nums)-1):
            if nums[i+1]==nums[i]:
                return True
        return False
        

        #通过字典来判断。测试通过,但是效率不怎么高
        if len(nums)==1:
            return False
        d = {}
        for i in nums:
            if d.get(i) is not None:
                return True
            else:
                d[i]=i
        return False
        """
        

总结:

基本思路:

  1. 利用set函数将列表转换成集合,集合不允许重复元素,判断两者长度。
  2. 将列表排序,比较前后有无重复元素。
  3. 利用字典遍历。

只出现一次的数字

Given a non-empty array of integers, every element appears twice except for one. Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

Example:

Input: [2,2,1]
Output: 1

Code(By myself):

算法:若列表长度为1,则该元素即为只出现一次的数字;若列表长度大于1,排序列表,以步长为2遍历列表,某数字与其后数字不相等,则为只出现一次;若遍历结束,则只出现一次的数字为最后一个元素。

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        nums.sort()
        for i in range(0,len(nums)-1,2):
            if nums[i] != nums[i+1]:
                return nums[i]
        return nums[len(nums)-1]
class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in set(nums):
            if nums.count(i) == 1:
                return i

利用list.count()遍历,计算列表中每一个元素出现的次数,不过由于时间超出限制,未能通过。


Code(Others):

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        result = 0
        for x in nums:
            result ^= x
        return result

^=:异或,a^=b,对a和b按位比较,若相等则该位为0,负责为1,最终结果为只出现一次的数字。


class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # return 2*sum(set(nums))-sum(nums)
        
        dic={}
        for i in nums:
            if i in dic.keys():
                dic.pop(i)
            else:
                dic[i]=1
        return dic.popitem()[0]

利用字典遍历列表,若i是字典dic的键值key,则调用dic.pop()删除该键值对;负责将其加入字典遍历结束之后字典键值仅剩下出现一次的数字,返回该值。

pop(key):

如果键值key存在与字典中,删除dict[key],返回 dict[key]的value值。key值必须给出。
否则,返回default值。如果default值没有过出,就会报出KeyError异常。
pop()方法至少接受一个参数,最多接受两个参数。
popitem()
删除,并且返回一个键值对(key,value)形式。
如果字典已经为空,却调用了此方法,就报出KeyError异常。

总结:

思路:

  1. 排序后判断相邻两元素是否相等
  2. 利用异或进行遍历
  3. 利用字典进行遍历

两个数组的交集 II

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2, 2].

Note:

  • Each element in the result should appear as many times as it shows in both arrays.
  • The result can be in any order.

Follow up:

  • What if the given array is already sorted? How would you optimize your algorithm?
  • What if nums1's size is small compared to nums2's size? Which algorithm is better?
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?
Code(by myself):
class Solution:
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        dic = {}
        nums = []
        for x in nums1:
            if x in dic:
                dic[x] += 1
            else:
                dic[x] = 1
        for x in nums2:
            if x in dic:
                nums.append(x)
                dic[x] -= 1
                if dic[x] == 0:
                    dic.pop(x)
        return nums

Code(others):
class Solution:
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        a = nums1.copy()
        b = nums2.copy()
        a.sort()
        b.sort()
        c = list()
        i = 0
        j = 0
        while i < len(a) and j < len(b):
            if a[i] == b[j]:
                c.append(a[i])
                i += 1
                j += 1
            elif a[i] < b[j]:
                i += 1
            else:
                j += 1
        return c
总结:

  1. 将nums1中每个元素当初dic中key值,其出现次数为value,比对nums2和dic,找出交集
  2. 将两列表排序,逐步比较找出交集

加一

Given a non-empty array of digits representing a non-negative integer, plus one to the integer.

The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.

You may assume the integer does not contain any leading zero, except the number 0 itself.

Example:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Code(by myself):
class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        s = ''
        for x in digits:
            s = s + str(x)
        digits.clear()
        s = int(s)
        s += 1
        s = str(s)
        for x in s:
            digits.append(int(x))
        return digits

可优化为:

class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        num = 0
        for i in range(len(digits)):
            num = num*10 + digits[i]
        return [int(i) for i in str(num+1)]
Code(others):
class Solution:
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        t = digits.copy()
        
        carry = 1
        for i in range(len(t)-1, -1, -1):
            t[i] += carry
            carry = 0
            if t[i] >= 10:
                t[i] %= 10
                carry = 1
        if carry == 1:
            t.insert(0, 1)
        return t
总结:
  1. 将列表转换成数值,加一后再转化成列表
  2. 利用标识符逐位进行计算

移动零

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.

Note:

  1. You must do this in-place without making a copy of the array.
  2. Minimize the total number of operations.
Example:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
Code(by myself):
class Solution:
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        j = 0
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[j] = nums[i]
                j += 1

        nums[j:] = [0 for a in range(j,i+1)]
Code(others):
class Solution:
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        j = 0
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[j], nums[i] = nums[i], nums[j]
                j += 1
总结:
利用两个指针遍历列表,交换零与非零元素位置。

两数之和

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

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

Example:
给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
Code(by myself):
class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        num = nums.copy()
        num.sort()
        i = 0
        j = len(nums) - 1
        while i <= j :
            if num[i] + num[j] > target:
                j -= 1
            elif num[i] + num[j] < target:
                i += 1
            else:
                a = nums.index(num[i])
                if num[i] == num[j]:
                    nums.remove(num[i])
                    b = nums.index(num[j]) + 1
                else:
                    b = nums.index(num[j])
                return [a,b]
Code(others):
dic = {}
        for i in range(len(nums)):
            if target-nums[i] in dic:
                return [i,dic[target-nums[i]]]
            else:
                dic[nums[i]] = i
总结:
  1. 排序后利用一前一后两指针寻找两个元素
  2. 利用字典查找

有效的数独

Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

  1. Each row must contain the digits 1-9 without repetition.
  2. Each column must contain the digits 1-9 without repetition.
  3. Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.


A partially filled sudoku which is valid.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

Code(by myself):
class Solution:
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        for x in board:
            a = [i for i in x if i != '.']
            if len(a) != len(set(a)):
                return False
            
        for j in range(9):
            a = []
            for i in range(9):
                if board[i][j] != '.':
                    a.append(board[i][j])
            if len(a) != len(set(a)):
                return False
            
        blocks_origin = [board[row][column] for x in [[0,1,2],[3,4,5],[6,7,8]] for y in [[0,1,2],[3,4,5],[6,7,8]] for row in x for column in y]
        blocks = [[blocks_origin[row*9+column] for column in range(9)]for row in range(9)] 
        for x in blocks:
            a = [i for i in x if i != '.']
            if len(a) != len(set(a)):
                return False
              
        return True
Code(others):
Grid, Col, Row = [''] * 9, [''] * 9, [''] * 9

        for idx, row in enumerate(board):
            for i, ch in enumerate(row):
                if ch != '.':
                    GridIndx =  idx // 3 * 3 + i // 3
                    if ch in Row[idx] or ch in Col[i] or ch in Grid[GridIndx]:
                        print(ch, Grid, Col, Row)
                        return False
                    Row[idx] += ch
                    Col[i] += ch
                    Grid[GridIndx] += ch
                    
        return True
总结:
  1. 分别提取出行、列、块为列表,判断有无重复元素
  2. 利用enumerate()函数将数独编号,将行、列、块分别存储在9个列表中,若出现重复则返回False

旋转图像

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Note:

You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

Example:
Given input matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

rotate the input matrix in-place such that it becomes:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]
Code(by myself):
class Solution:
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        for i in range(len(matrix)):
            j = i + 1
            while j < len(matrix):
                matrix[i][j] , matrix[j][i] = matrix[j][i] , matrix[i][j] ##转置矩阵
                j += 1
            matrix[i].reverse() ##转置行向量
Code(others):
class Solution:
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        
        length = len(matrix) - 1

        def rotation(matrix, p, y):
            # 每次旋转外围一圈,p作为起始点,依次为(0, 0), (1, 1), (2, 2)... 
            # y作为外圈的另一个点,在p的对角上
            # 每次旋转4个点(值交换)
            if p[1] < y:

                matrix[p[0]][p[1]], matrix[p[1]][y], matrix[y][length-p[1]], matrix[length-p[1]][p[0]] = (
                    matrix[length-p[1]][p[0]], matrix[p[0]][p[1]], matrix[p[1]][y], matrix[y][length-p[1]]
                )

                rotation(matrix, [p[0], p[1]+1], y)

        for i in range(len(matrix) // 2):  # 后部分已经算过
            rotation(matrix, [i, i], length - i)
总结:
  1. 将图像转置后并将每行转置即为所求
  2. 每次旋转4个点,循环结果即为所求



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值