练习大纲
20.有效的括号
26.删除排序数组中的重复项
11.盛最多水的容器
43.字符串相乘
43.字符串相乘(Java实现,python可以高精度乘法)
预备知识:
对于计算机无法用普通数据类型(如:longint)表示的大整数进行乘法运算,称为高精度乘法。
Java,c++没有提供高精度的计算方案,,所以大整数的运算都需要手动实现。
Python已经为我们提供了高精度运算, 这里用Java代码实现高精度加法运算的原理。高精度加法的过程就是完全模拟列竖式计算的方式。
题目如下:
给定两个以字符串形式表示的非负整数 num1
和 num2
,返回 num1
和 num2
的乘积,它们的乘积也表示为字符串形式。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
说明:
num1
和num2
的长度小于110。num1
和num2
只包含数字0-9
。num1
和num2
均不以零开头,除非是数字 0 本身。- 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
int n1 = num1.length();
int n2 = num2.length();
int[] pos = new int[n1 + n2];
for (int i = n1 - 1; i >= 0; i--) {
for (int j = n2 - 1; j >= 0; j--) {
int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
int sum = mul + pos[i + j + 1];
pos[i + j] += sum / 10;
pos[i + j + 1] = sum % 10;
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < pos.length; i++) {
if (i == 0 && pos[i] == 0) {
continue;
}
sb.append(pos[i]);
}
return sb.toString();
}
11.盛最多水的容器
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
先写了暴力法,算法时间复杂度O(n^2),超时未通过。
class Solution:
def maxArea(self, height: List[int]) -> int:
maxarea = 0
for i in range(0, len(height)):
for j in range(i + 1, len(height)):
maxarea = max(maxarea, min(height[i], height[j]) * (j - i))
return maxarea
解题思路:双指针法
1.定义两个指针,l 和 r,初始时,指向首部和尾部;
2.计算两个指针之间的面积:area = min(height[l], height[r]) * (r - l)
3.循环不断比较当前面积和存在的最大面积:maxarea = max(maxarea , area)
4.height[l]和height[r],谁小谁往里面走
class Solution:
def maxArea(self, height: List[int]) -> int:
maxarea = 0
l = 0
r =len(height) - 1
while l < r :
maxarea = max(maxarea, min(height[l], height[r]) * (r - l))
if height[l] < height[r]:
l += 1
else:
r -= 1
return maxarea
26.删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1,2。
你不需要考虑数组中超出新长度后面的元素。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
#双指法
if len(nums) <= 1:
return len(nums)
i = 0 #慢指针i,快指针j
for j in range(1, len(nums)):
if nums[j] != nums[i]:
i += 1
nums[i] = nums[j]
return i + 1
20.有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
题解:参考大佬的优化版
class Solution:
def isValid(self, s):
'''
:type s: str
:rtype: bool
'''
stack = []
match = {')':'(', '}':'{', ']':'['}
for c in s:
#如果c是左括号
if c not in match:
stack.append(c)
#如果c是右括号
#若栈空返回不合法
#和栈顶元素对比是否相匹配,如果不匹配,返回不合法
elif not stack or match[c] != stack.pop():
return False
#如果栈空返回True
return not stack