数组
前言:为了巩固自己的python基础,这里每一个最优解法我都用使用python和java来编写。
数组的存储
数组的存储:c为每个元素占用的存储空间字节数
一维数组a[n]:Loc(a[i]) = Loc(a[0]) + i * c
二维数组a[m, n]:Loc(a[i, j]) = Loc(a[0, 0]) + (i * n + j) * c
三维数组a[m, n, l]:Loc(a[i, j, k]) = Loc(a[0, 0, 0]) + (i * n * l + j * l + k) * c
题目解析
两数之和
1.题目描述
2.解题思路及代码
- 朴素做法:O(n^2)
双重for循环,直接判断两个下标的和是否等于target,等于直接输出结果。
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i ++ ) {
for (int j = i + 1; j < nums.length; j ++ ) {
if (nums[i] + nums[j] == target) return new int[]{i, j};
}
}
return new int[]{0, 0};
}
- 使用哈希表:O(n)
使用HashMap将数据存放到哈希表中,遍历每个元素,查找哈希表中是否包含target - x,如果包含直接返回结果,不包含继续遍历。
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i ++ ) {
if (map.containsKey(target - nums[i]))
return new int[] {map.get(target - nums[i]), i};
map.put(nums[i], i);
}
return new int[0];
}
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
map = dict()
for i, num in enumerate(nums):
if target - num in map:
return [map[target - num], i]
map[num] = i
return []
最接近的三数之和
1.题目描述
2.解题思路及代码
- 朴素做法:O(n^3)
三重循环,枚举三个数,判断他们的和与target的绝对值,返回绝对值最小的和
public int threeSumClosest(int[] nums, int target) {
int res = 0, subtract = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i ++ ) {
for (int j = i + 1; j < nums.length; j ++ ) {
for (int k = j + 1; k < nums.length; k ++ ) {
int tmp = nums[i] + nums[j] + nums[k];
if (Math.abs(tmp - target) < subtract) {
subtract = Math.abs(tmp - target);
res = tmp;
}
}
}
}
return res;
}
- 排序+双指针:O(n^2)
对数组排序,枚举第一个元素,然后使用双指针枚举第二个和第三个元素,最后返回结果。
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int best = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length - 2; i ++ ) {
int st = i + 1, ed = nums.length - 1;
while(st < ed) {
int sum = nums[i] + nums[st] + nums[ed];
if (Math.abs(sum - target) < Math.abs(best - target)) {
best = sum;
}
if (sum < target) st ++ ;
else if (sum > target) ed --;
else return best;
}
}
return best;
}
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
best = nums[0] + nums[1] + nums[2]
for i in range(len(nums)):
st = i + 1
ed = len(nums) - 1
while st < ed:
s = nums[i] + nums[st] + nums[ed]
if (abs(s - target) < abs(best - target)):
best = s
if (s < target):
st += 1
elif s > target:
ed -= 1
else:
return target
return best
移除元素
1.题目描述
2.解题思路及代码
- 快慢指针:O(n)
使用left表示最后数组的长度,right判断数组的元素是否等于val,不等于val就放入left指向的数组中。
public int removeElement(int[] nums, int val) {
int l = 0, r = 0;
while(r < nums.length) {
if (nums[r] != val) {
nums[l ++ ] = nums[r];
}
r ++ ;
}
return l;
}
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
l = 0
for i in range(len(nums)):
if nums[i] != val:
nums[l] = nums[i]
l += 1
return l
删除有序数组中的重复项
1.题目描述
2.解题思路及代码
- 快慢指针:O(n)
使用left指向数组最左边,判断left和right是否相等,不相等则将right放入left后面的元素中,最后返回left+1,注意当nums数组为0时需要特判。
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int l = 0;
for (int i = 1; i < nums.length; i ++ ) {
if (nums[i] != nums[l]) {
l ++ ;
nums[l] = nums[i];
}
}
return l + 1;
}
另一种做法:判断right和right-1的元素是否相等,不相等则放入left中,然后left++
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
l = 0
for i in range(len(nums)):
if i == 0 or nums[i] != nums[i - 1]:
nums[l] = nums[i]
l += 1
return l
三数之和
1.题目描述
2.解题思路及代码
本题是需要获取具体的数组元素,而不是数组下标,因此使用哈希表获取结果比较困难。这里首先对数组进行排序,然后确定第一个元素,然后确定第二个元素,第三个元素默认从最后一个元素获取,然后判断结果和0的差距,如果大,则回退。
同时需要注意,因为需要保证元素相同的算是同一个结果,因此如果第一个元素循环的时候如果和前一个元素相同,则不需要进行循环,第二个元素也需要同样的判断。只要保证第一个元素和第二个元素不重复,那么最后的结果一定是不重复的。
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
for (int i = 0; i < nums.length; i ++ ) {
// 保证第一个元素不是重复的
if (i > 0 && nums[i] == nums[i - 1]) continue;
int k = nums.length - 1;
for (int j = i + 1; j < nums.length; j ++ ) {
// 保证第二个元素不是重复的
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
while (nums[j] + nums[k] + nums[i] > 0 && j < k) k -- ;
if (k == j) break;
if (nums[j] + nums[k] + nums[i] == 0) {
List<Integer> list = new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
ans.add(list);
}
}
}
return ans;
}
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()
for i in range(n):
if i > 0 and nums[i] == nums[i - 1]:
continue
k = n - 1
for j in range(i + 1, n):
if j > i + 1 and nums[j] == nums[j - 1]:
continue
while j < k and nums[j] + nums[k] + nums[i] > 0:
k -= 1
if j == k:
break
if nums[k] + nums[j] + nums[i] == 0:
ans.append([nums[i], nums[j], nums[k]])
return ans