数据结构(Python实现)------数组与字符串

数据结构(Python实现)------ 数组与字符串

数组

本章节中,我们将介绍两个重要的概念:数组和动态数组。

这是你应当熟悉的基本数据结构。 我们也为你提供了使用内置的数组和动态数组的教程。

完成本章后,你将能够回答以下问题:

1、数组和动态数组之间有什么不同?
2、在你常用的语言中,数组和动态数组对应的内置数据结构是什么?
3、如何在数组中执行初始化、数据访问、修改、迭代、排序等基本操作?
4、如何在动态数组中执行初始化、数据访问、修改、迭代、排序、添加、删除等基本操作?

基本概念

数组

在这里插入图片描述

动态数组

在这里插入图片描述

Python实现

寻找数组的中心索引

给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。

我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。

如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
示例 1:

输入: 
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释: 
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。

示例 2:

输入: 
nums = [1, 2, 3]
输出: -1
解释: 
数组中不存在满足此条件的中心索引。

说明:
nums 的长度范围为 [0, 10000]。
任何一个 nums[i] 将会是一个范围在 [-1000, 1000]的整数。

class Solution(object):
    def pivotIndex(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left_sum = 0
        right_sum = sum(nums)

        for index,item in enumerate(nums):
            right_sum -= item

            if left_sum == right_sum:
                return index

            left_sum += item
        return -1

至少是其他数字两倍的最大数

在一个给定的数组nums中,总是存在一个最大元素 。

查找数组中的最大元素是否至少是数组中每个其他数字的两倍。

如果是,则返回最大元素的索引,否则返回-1。

示例 1:

输入: nums = [3, 6, 1, 0]
输出: 1
解释: 6是最大的整数, 对于数组中的其他整数,
6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1.

示例 2:

输入: nums = [1, 2, 3, 4]
输出: -1
解释: 4没有超过3的两倍大, 所以我们返回 -1.

提示:

nums 的长度范围在[1, 50].
每个 nums[i] 的整数范围在 [0, 100].

class Solution(object):
    def dominantIndex(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i = nums.index(max(nums))
        nums = sorted(nums)


        if len(nums) == 1:
            return 0

        if nums[-1] >= nums[-2]*2:
            return i


        return -1

加一

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        lens = len(digits)
        divisor = 1
        res = 0
        for i in range(0,lens):
            res +=digits[-(i+1)]*divisor
            #print(res)

            divisor *= 10

        res += 1
        res = [int(x) for x in str(res)]
        return res

二维数组

类似于一维数组,二维数组也是由元素的序列组成。但是这些元素可以排列在矩形网格中而不是直线上。

基本概念

Python实现

对角线遍历

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。

示例:
在这里插入图片描述
说明:
给定矩阵中的元素总数不会超过 100000

class Solution(object):
    def findDiagonalOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        # 向右上方走,x -= 1, y += 1
        # 向左下角走,x += 1, y -= 1
        m = len(matrix)
        if not m :
            return []
        n = len(matrix[0])
        if not n :
            return []
 
        cnt = 0
        x, y = 0, 0
        res = list()
        direction = "right"
        while(cnt < m * n):
            cnt += 1
            # print direction, x, y, matrix[x][y]
            res.append(matrix[x][y])
            if direction == "right":#向右上方走
                if x >= 1 and y < n - 1: # 不用调换方向
                    x -= 1
                    y += 1
                    continue
                else:
                    direction = "left" #调换方向
                    if x == 0 and y < n - 1: #碰上壁
                        y += 1
                    elif  y == n - 1: #碰右壁
                        x += 1
            else: # 向左下方走
                if x < m - 1 and y >= 1: # 不用调换方向
                    x += 1
                    y -= 1
                    continue
                else:
                    direction = "right" #调换方向
                    if x == m - 1: # 碰下壁
                        y += 1
                    elif y == 0 and x < m - 1: #碰左壁
                        x += 1 
            # print res
        return res

螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

输入:
[
 [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例 2:

输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

如果通过设定限制条件改变方向,来逐个遍历 (超时)

这里使用了 “方向变量” 来处理


class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        m = len(matrix)
        if m == 0:      #matrix为空
            return []

        if m == 1:      #matrix只有一个元素
            return matrix[0]

        n = len(matrix[0])

        if n == 0:
            return []

        li = []

        i,j,di,dj = 0,0,0,1
        for _ in range(m*n):
            li.append(matrix[i][j])
            matrix[i][j] = "MARK"
        
            #再次回到"MARK"时,就说明该转向了
            if matrix[(i+di)%m][(j+dj)%n] == "MARK":
                # 0 1 变 1 0, 1 0 变 0 -1, 0 -1 变 -1, 0, -1 0 变 0 1
                di,dj = dj,-di
            i += di
            j += dj
            
        return li

杨辉三角

在这里插入图片描述
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

class Solution(object):
    def generate(self, numRows):
        """
        :type numRows: int
        :rtype: List[List[int]]
        """
        res = []
        for i in range(numRows):
            temp = [1]*(i+1)
            res.append(temp)
            for j in range(1,i):
                res[i][j] = res[i-1][j-1] + res[i-1][j]

        return res

字符串

基本概念

Python实现

二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0。

示例 1:

输入: a = "11", b = "1"
输出: "100"

示例 2:

输入: a = "1010", b = "1011"
输出: "10101"

class Solution(object):
    def addBinary(self, a, b):
        """
        :type a: str
        :type b: str
        :rtype: str
        """
        a, b = int(a, 2), int(b, 2)
        # "0b" 是二进制数的标志,返回时需要通过切片[2:]去掉
        # "0b100"
        return bin(a+b)[2:]

实现 strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

利用Python特性解法:

 if needle  not in haystack:
            return -1
 return haystack.find(needle)

逻辑解法


class Solution:
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        i=0
        j=0
        if needle == "":
            return 0
        elif needle not in haystack:
            return -1
        if needle in haystack:
            l1=len(haystack)
            l2= len(needle)
            while i<l1 and j<=l2:
                if haystack[i] == needle[j]:
                    i+=1
                    j+=1
                else:
                    i=i-j+1
                    j=0
                if j==l2:
 
                    return i-l2

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"

示例 2:

输入: ["dog","racecar","car"]
输出: ""

解释: 输入不存在公共前缀。
说明:

所有输入只包含小写字母 a-z 。

双指针技巧

场景一

在前一章中,我们通过迭代数组来解决一些问题。通常,我们只使用从第一个元素开始并在最后一个元素结束的一个指针来进行迭代。 但是,有时候,我们可能需要同时使用两个指针来进行迭代。

示例
让我们从一个经典问题开始:

反转数组中的元素。

其思想是将第一个元素与末尾进行交换,再向前移动到下一个元素,并不断地交换,直到它到达中间位置。

我们可以同时使用两个指针来完成迭代:一个从第一个元素开始,另一个从最后一个元素开始。持续交换它们所指向的元素,直到这两个指针相遇。

以下代码可以供你参考:

int i = 0;
int j = N - 1;
while (i < j) {
    swap(v[i], v[j]);
    i++;
    j--;
}

}

总结
总之,使用双指针技巧的典型场景之一是你想要

从两端向中间迭代数组。

这时你可以使用双指针技巧:

一个指针从始端开始,而另一个指针从末端开始。

值得注意的是,这种技巧经常在排序数组中使用。

Python实现

反转字符串

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

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

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

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

示例 2:

输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

解法一:Python特性

    s.reverse()

解法二:

class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """

        for i in range(len(s)//2):
                tmp = s[i]
                s[i] = s[len(s) - 1 - i]
                s[len(s) - 1 - i] = tmp

数组拆分I

给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。

示例 1:

输入: [1,4,3,2]

输出: 4
解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4).

提示:

n 是正整数,范围在 [1, 10000].
数组中的元素范围在 [-10000, 10000].

class Solution(object):
    def arrayPairSum(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        listNums = list(nums)

        sum = 0
        listNums.sort()
        for i in range(0,len(listNums),2):
            sum += listNums[i]
        return sum

两数之和 II - 输入有序数组

给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:

输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

解法1:最直白的笨办法,双循环。时间复杂度:O(n^2),超时!!!


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

解法2:通过字典建立索引列表,将每个差值和对应下标,保存在字典列表中,然后同时输出。 时间复杂度:O(n)。

class Solution(object):
    def twoSum(self,numbers,target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """

        dic = {}
        li = []
        for i in range(len(numbers)):
            if numbers[i] in dic.keys():
                #将原始值和差值的下标分别添加到li中
                li.append(dic[numbers[i]]+1)
                li.append(i+1)
                return li
            #将每个值得差值以及对应的下标,保存在字典里
            dic[target-numbers[i]] = i

        return None

场景二

有时,我们可以使用两个不同步的指针来解决问题。

示例
让我们从另一个经典问题开始:

给定一个数组和一个值,原地删除该值的所有实例并返回新的长度。

如果我们没有空间复杂度上的限制,那就更容易了。我们可以初始化一个新的数组来存储答案。如果元素不等于给定的目标值,则迭代原始数组并将元素添加到新的数组中。

重新考虑空间限制
现在让我们重新考虑空间受到限制的情况。

我们可以采用类似的策略,我们继续使用两个指针:一个仍然用于迭代,而第二个指针总是指向下一次添加的位置。

实际上,它相当于使用了两个指针,一个用于原始数组的迭代,另一个总是指向新数组的最后一个位置。

int removeElement(vector<int>& nums, int val) {
    int k = 0;
    for (int i = 0; i < nums.size(); ++i) {
        if (nums[i] != val) {
            nums[k] = nums[i];
            ++k;
        }
    }
    return k;
}

在上面的例子中,我们使用两个指针,一个快指针 i 和一个慢指针 k 。i 每次移动一步,而 k 只在添加新的被需要的值时才移动一步。

总结
这是你需要使用双指针技巧的一种非常常见的情况:

同时有一个慢指针和一个快指针。

解决这类问题的关键是

确定两个指针的移动策略。

与前一个场景类似,你有时可能需要在使用双指针技巧之前对数组进行排序,也可能需要运用贪心想法来决定你的运动策略。

Python实现

移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。
示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。
说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}


class Solution:
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        while val in nums:
            nums.pop(nums.index(val))
        return len(nums)

最大连续1的个数

给定一个二进制数组, 计算其中最大连续1的个数。

示例 1:

输入: [1,1,0,1,1,1]
输出: 3

解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.

注意:

输入的数组只包含 0 和1。
输入数组的长度是正整数,且不超过 10,000。

解法1:用一个列表 MaxConsecutiveOnes来统计所有的长度k,然后选出最大的max( MaxConsecutiveOnes)。

class Solution(object):
    def findMaxConsecutiveOnes(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        MaxConsecutiveOnes = []
        k = 0
        for i in nums:

            if i == 1:
                k += 1

            else:
                MaxConsecutiveOnes.append(k)
                k = 0

        MaxConsecutiveOnes.append(k)

        return max(MaxConsecutiveOnes)

解法2: 相比解法1,设立一个最大长度变量maxNum来实时记录最大值,只有当临时最大长度temp大于它时,才进行交换。

class Solution2(object):
    def findMaxConsecutiveOnes(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        temp = 0
        MaxLens = 0
        for i in nums:
            if i == 1:
                temp += 1

            elif temp > MaxLens:
                MaxLens = temp
                temp = 0

            else:
                temp = 0

            if temp > MaxLens:
                MaxLens = temp

        return MaxLens

解法3:根据只有0和1的条件,设置巧妙的置零操作sum = sum*num + num。

class Solution3(object):
    def findMaxConsecutiveOnes(self, nums):
        """
            :type nums: List[int]
            :rtype: int
            """
        sum = 0
        MaxLens = 0

        for num in nums:
            sum = num * sum + num

            if sum > MaxLens:
                MaxLens = sum

        return MaxLens

长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

示例:

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2

解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:

如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。

解法1:最容易想到的方法,直接遍历所有可能的组合。时间复杂度:O(n^2)


class Solution(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        li = []
        for i in range(len(nums)-1):
            for j in range(i+1,len(nums)+1):
                if sum(nums[i:j]) >= s:
                    li.append(len(nums[i:j]))

        if len(li) == 0:
            return 0
        else:
            return min(li)


解法2:使用python自带的 enumerate() 方法来遍历。时间复杂度:O(n^2)

class Solution2(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0

        minLen = len(nums)+1
        for i,_ in enumerate(nums):
            total = 0
            for j,tmp in enumerate(nums[i:]):
                total += tmp
                if total >= s:
                    minLen = min(minLen,j+1)

        #r如果没有发生任何替换,说明替换
        if minLen == len(nums) + 1:
            return 0

        return minLen

解法3: 双指针,或对撞指针。不断判断跟s的大小,如果大了,说明元素太多,左移;反之小了,右移。时间复杂度:O(n)

class Solution3(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0

        #创建两个指针
        pointer1,pointer2 = 0,0
        total = 0
        nums_len = len(nums)
        minL = nums_len+1
        while pointer1 < nums_len:
            if pointer2 < nums_len and total < s:
                total += nums[pointer2]
                pointer2 += 1

            else:
                total -= nums[pointer1]
                pointer1 += 1

            if total >= s:
                minL = min(minL,pointer2-pointer1)

        if minL == nums_len + 1:
            return 0
        return minL

解法4:因为涉及到 “连续子数组”,一旦提到连续二字,我们想到可以通过 二分法 来简化处理。时间复杂度:O(nlog(n))。

class Solution4(object):
    def sumJudge(self,nums,index,s):
        sum = 0
        for i,_j in enumerate(nums):
            if i >= index:
                sum -= nums[i-index]

            sum += nums[i]

            if sum >= s:
                return True
        return False

    def minSubArrayLen(self,s,nums):

        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0

        left = 1
        right = len(nums)
        result = 0

        while left <= right:
            mid = left + (right-left)//2
            if self.sumJudge(nums,mid,s):
                right = mid - 1
                result = mid

            else:
                left = mid +1

        return result

解法5:动态规划法,不需要每次循环都计算加和。时间复杂度:O(nlog(n))。

class Solution5(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        res = len(nums) + 1
        low,high = 0,-1
        subsum = 0
        while(low < len(nums)):
            if (subsum < s) and (high + 1 < len(nums)):
                high += 1
                subsum += nums[high]
            else:
                subsum -= nums[low]
                low += 1

            if subsum >= s:
                res = min(res, high - low + 1)
        return res if res != len(nums) + 1 else 0

数组相关技术

基本概念

你可能想要了解更多与数组相关的数据结构或技术。我们不会深入研究这张卡片中的大多数概念,而是在本文中提供相应卡片的链接。

  1. 这里有一些其他类似于数组的数据结构,但具有一些不同的属性:

    字符串(已包含在本卡片中)
    哈希表
    链表
    队列

  2. 正如我们所提到的,我们可以调用内置函数来对数组进行排序。但是,理解一些广泛使用的排序算法的原理及其复杂度是很有用的。

  3. 二分查找也是一种重要的技术,用于在排序数组中搜索特定的元素。

  4. 我们在这一章中引入了双指针技巧。想要灵活运用该技技巧是不容易的。这一技巧也可以用来解决:

    链表中的慢指针和快指针问题
    滑动窗口问题

  5. 双指针技巧有时与贪心算法有关,它可以帮助我们设计指针的移动策略。 在不久的将来,我们会提供更多的卡片来介绍上面提到的这些技术,并更新链接。

Python实现

旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: [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]
示例 2:

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]

解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:

尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。

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


class Solution2(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        l = len(nums)
        k = k%l
        nums[:l-k] = reversed(nums[:l-k])
        nums[l-k:] = reversed(nums[l-k:])
        nums[:] = reversed(nums)

        return nums

class Solution3(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        def rev(start,end,nums):
            while start<end:
                nums[start],nums[end] = nums[end],nums[start]
                start += 1
                end -= 1

        l = len(nums)
        k = k%l
        rev(0, l - k - 1, nums)
        rev(l - k, l - 1, nums)
        rev(0, l - 1, nums)
        return nums


杨辉三角 II

在这里插入图片描述
示例:

输入: 3
输出: [1,3,3,1]

方法一

class Solution(object):
    def getRow(self, rowIndex):
        """
        :type rowIndex: int
        :rtype: List[int]
        """
        p = [1]
        if not rowIndex:
            return p
        for i in range(rowIndex):
            s = list(map(lambda  x,y:x+y,[0]+p,p+[0]))
            print(s)
            p = s
        return s

方法二

class Solution2(object):
    def getRow(self, rowIndex):
        """
        :type rowIndex: int
        :rtype: List[int]
        """
        p = [1]
        if not rowIndex:
            return p
        for j in range(rowIndex):
            p = [1] + [p[i]+p[i+1] for i in range(len(p)-1)] +[1]

        return p

翻转字符串里的单词

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:

输入: "the sky is blue"
输出: "blue is sky the"

示例 2:

输入: "  hello world!  "
输出: "world! hello"

解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:

输入: "a good   example"
输出: "example good a"

解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

无空格字符构成一个单词。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

class Solution:
    def reverseWords(self, s):
        return " ".join(s.strip().split()[::-1])

反转字符串中的单词III

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入: “Let’s take LeetCode contest”
输出: “s’teL ekat edoCteeL tsetnoc”
注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

class Solution(object):
    def reverseWords(self,s):
        """
        :type s: str
        :rtype: str
        """
        return " ".join(word[::-1] for word in s.split(" "))

删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。
示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。
说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

class Solution(object):
    def removeDuplicates(self,nums):
        i = 0
        while i < len(nums)-1:
            if nums[i] == nums[i+1]:
                nums.remove(nums[i])
            else:
                i = i+1

        return len(nums)

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
方法一:暴力法


class Solution:
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        for i in range(nums.count(0)):
            nums.remove(0)
            nums.insert(len(nums) - i, 0)

方法二:双指针法

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        j = 0
        for i in range(len(nums)):
            if nums[i] != 0:
                nums[i],nums[j] = nums[j],nums[i]
                j += 1
        
发布了64 篇原创文章 · 获赞 9 · 访问量 4347

猜你喜欢

转载自blog.csdn.net/Avery123123/article/details/103342494