一、两数之和
给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。(注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到)
数据范围:2≤len(numbers)≤105,−10≤numbersi≤109,0≤target≤109
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
import java.util.*;
public class Solution {
// 二分查找
private int binarySearch(int[][] nums, int i, int j, int target) {
while (i <= j) {
int mid = (i + j) / 2;
if (nums[mid][0] == target) return mid;
if (nums[mid][0] > target) j = mid - 1;
else i = mid + 1;
}
return -1;
}
public int[] twoSum (int[] numbers, int target) {
//排序, 双指针 第二个数可二分查找 空间O(n) 时间O(nlogn)
int[][] nums = new int[numbers.length][2]; // numbers[i]及其下标+1
for (int i = 0; i < numbers.length; i++) {
nums[i][0] = numbers[i];
nums[i][1] = i + 1;
}
Arrays.sort(nums, (a, b)->a[0] - b[0]); // 排序
for (int i = 0; i < nums.length; i++) {
int j = binarySearch(nums, i + 1, nums.length - 1, target - nums[i][0]); // 二分查找
if (j > 0) {
int x = nums[i][1], y = nums[j][1];
return new int[] {Math.min(x,y), Math.max(x,y)};
}
}
return null;
}
}
运行结果

二、数组中出现次数超过一半的数字
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
数据范围:n≤50000,数组中元素的值 0≤val≤10000
要求:空间复杂度:O(1),时间复杂度 O(n)

import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型一维数组
* @return int整型
*/
public int MoreThanHalfNum_Solution (int[] numbers) {
// write code here
int candidate = 0;
int count = 0;
for (int n : numbers) {
if (count == 0) {
candidate = n;
}
if (n == candidate) {
count++;
} else {
count--;
}
}
return candidate;
}
}
运行结果

三、数组中只出现一次的两个数字
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
数据范围:数组长度 2≤n≤1000,数组中每个数的大小 0<val≤1000000
要求:空间复杂度 O(1),时间复杂度 O(n)
提示:输出时按非降序排列。

import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型一维数组
*/
public int[] FindNumsAppearOnce (int[] nums) {
// write code here
// 先排序
Arrays.sort(nums);
// 结果list
List<Integer> list = new ArrayList<Integer>();
// 遍历
for (int i = 0; i < nums.length; i++) {
// 如果是第一个,只比较后面一个
if (i == 0) {
if (nums[i] != nums[i + 1]) {
list.add(nums[i]);
}
} else if (i == nums.length -
1) { // 如果是最后一个,只比较前面一个
if (nums[i] != nums[i - 1]) {
list.add(nums[i]);
}
} else { // 比较左右两个
if (nums[i] != nums[i + 1] && nums[i] != nums[i - 1]) {
list.add(nums[i]);
}
}
}
return list.stream()
.mapToInt(Integer::intValue)
.toArray();
}
}
运行结果

四、缺失的第一个正整数
给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数
进阶: 空间复杂度 O(1),时间复杂度 O(n)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int minNumberDisappeared (int[] nums) {
// 算法核心思想:通过按正整数顺序的方式创建哈希记录,遍历数组登记哈希,然后遍历哈希
// 算法时间复杂度O(N),额外空间复杂度O(N)(没做到O(1))
// 1.遍历数组,记录数组中出现过的最小正整数值,并将所有正整数记录哈希表
// 记录最小值是为了简化判断,若最小值>1可以直接返回1
int min = Integer.MAX_VALUE;
HashMap<Integer, Boolean> hm = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
hm.put(nums[i], true);
if (nums[i] < min) {
min = nums[i];
}
}
}
if (min > 1) {
// 若数组中出现过的最小正整数比1大,则可直接输出最小正整数1
return 1;
}
// 其余情况均为从1开始出现,直到某个值没有出现
// 2.从1开始遍历HashMap,输出最早未登记的key
int i = 2;
while (hm.containsKey(i)) {
i++;
}
return i;
}
}
运行结果

五、三数之和
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。

import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
int n = num.length;
Arrays.sort(num);
for (int i = 0; i < n - 2; i++) {
if (i != 0 && num[i] == num[i - 1]) {
continue;
}
int l = i + 1, r = n - 1;
while (l < r) {
if (num[i] + num[l] + num[r] < 0) {
while (++l < r && num[l] == num[l - 1]) {}
} else if (num[i] + num[l] + num[r] > 0) {
while (l < --r && num[r] == num[r + 1]) {}
} else {
res.add(new ArrayList<>(Arrays.asList(num[i], num[l], num[r])));
while (++l < r && num[l] == num[l - 1]) {}
while (l < --r && num[r] == num[r + 1]) {}
}
}
}
return res;
}
}
运行结果

455



被折叠的 条评论
为什么被折叠?



