1. 两数之和
今日主题:数组
问题描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
解题思路1-暴力破解法
双层for循环遍历,找到符合条件的两个数时跳出循环
代码实现1-暴力法
class Solution {
public int[] twoSum(int[] nums, int target) {
int size = nums.length;
int[] result = new int[2];
for(int i = 0; i < size; i++){
for(int j = i + 1; j < size; j++){
if(nums[i] + nums[j] == target){
result[0] = i;
result[1] = j;
break;
}
}
}
return result;
}
}
- 时间复杂度O(n^2)
- 空间复杂度O(1)
解题思路2-哈希表
利用哈希表,将寻找target-nums[i]的时间复杂度缩短至O(1)
代码实现2-哈希表
class Solution {
public int[] twoSum(int[] nums, int target) {
int size = nums.length;
int[] res = new int[2];
//key为数组中元素的值,value为其下标
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
Integer matchKey = target - nums[i];
if(map.containsKey(matchKey)){
res[0] = map.get(matchKey);
res[1] = i;
}else{
map.put(nums[i], i);
}
}
return res;
}
}
15. 三数之和
问题描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
解题思路
首先,对数组进行排序;然后,用外层for循环遍历数组,取每次遍历的值为第一个元素nums[i];接着,使用双指针遍历nums[i]之后的元素。
- 注意,为了去重,每次移动指针时要移动至下一个不相同的元素。
代码实现
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int len = nums.length;
//对数组进行排序
Arrays.sort(nums);
List<List<Integer>> res = new LinkedList<>();
for(int i = 0; i < len - 2; i++){
if(i != 0 && nums[i] == nums[i - 1]){
//保证第一个元素不重复
continue;
}
int left = i + 1 ,right = len - 1;
while(left < right){
if(nums[left] + nums[right] < -nums[i]){
left++;
}else if(nums[left] + nums[right] > -nums[i]){
right--;
}else{
List<Integer> triple = new ArrayList(3);
triple.add(nums[i]);
triple.add(nums[left]);
triple.add(nums[right]);
res.add(triple);
//将左指针向右移向下一个不同的值,保证第二个元素不重复
left++;
while(left < right && nums[left - 1] == nums[left]){
left++;
}
//将右指针向左移向下一个不同的值,保证第三个元素不重复
right--;
while(right > left && nums[right + 1] == nums[right]){
right--;
}
}
}
}
return res;
}
}
31. 下一个排列
问题描述
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
解题思路
最开始的思路是,从后向前遍历找到第一个比最后一个元素小的元素进行交换,再将目标元素之后的元素用冒泡排序算法进行升序排列。但是,始终无法通过全部的测试用例,于是看了题解。原来我错在了不应该默认将最后一个元素作为“较大数”。
- 算法过程来自全leetcode题解区最好的题解!
下一个排列算法
代码实现
class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length;
if(len < 2){
return;
}
//1.从后向前遍历,找到第一个相邻升序对,nums[i]为高位的较小数
int i = len - 2;
while(i >= 0){
if(nums[i] < nums[i + 1]){
break;
}
i--;
}
//System.out.println("i="+i);
if(i == -1 ){
//不存在下一个更大的排列
reverse(nums, 0, len - 1);
return;
}
//2.从后向前遍历,找到最靠右的大于nums[i]的数,将其作为低位的较大数
int j = len - 1;
while(j > i){
if(nums[j] > nums[i]){
break;
}
j--;
}
//System.out.println("j="+j);
//3.将较大数与较小数进行交换
swap(nums, i , j);
//4.将nums[i]之后的元素进行逆置,升序排列
reverse(nums, i + 1, len -1);
}
//将数组中[l,r]区间中的元素进行反转
public void reverse(int[] nums, int l, int r){
while(l < r){
swap(nums, l++, r--);
}
}
public void swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
网友评论