1、两数之和:
题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍
方法一:
public static int[] twoSum1(int[] nums, int target){
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
方法二:
public static int[] twoSum2(int[] nums, int target){
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
方法三:
public int[] twoSum3(int[] nums, int target) {
int m=0,n=0,k,board=0;
int[] res=new int[2];
int[] tmp1=new int[nums.length];
System.arraycopy(nums,0,tmp1,0,nums.length);
Arrays.sort(nums);
for(int i=0,j=nums.length-1;i<j;){
if(nums[i]+nums[j]<target){
i++;
}
else if(nums[i]+nums[j]>target){
j--;
}
else if(nums[i]+nums[j]==target){
m=i;
n=j;
break;
}
}
for(k=0;k<nums.length;k++){
if(tmp1[k]==nums[m]){
res[0]=k;
break;
}
}
for(int i=0;i<nums.length;i++){
if(tmp1[i]==nums[n]&&i!=k){
res[1]=i;
}
}
return res;
}
2、删除排序数组中的重复项
题目:给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。(
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 [1,2]
方法一:
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int i = 0;
for (int j = 1; j < nums.length; j++) {
if (nums[j] != nums[i]) {
i++;
nums[i] = nums[j];
}
}
return i + 1;
}
3、杨辉三角
题目:给定一个非负整数 numRows,生成杨辉三角的前 numRows 行:
方法一:
public static List<List<Integer>> method1(int numRows) {
List<List<Integer>> triangle = new ArrayList<List<Integer>>();
// First base case; if user requests zero rows, they get zero rows.
if (numRows == 0) {
return triangle;
}
// Second base case; first row is always [1].
triangle.add(new ArrayList<>());
triangle.get(0).add(1);
for (int rowNum = 1; rowNum < numRows; rowNum++) {
List<Integer> row = new ArrayList<>();
List<Integer> prevRow = triangle.get(rowNum-1);
// The first row element is always 1.
row.add(1);
// Each triangle element (other than the first and last of each row)
// is equal to the sum of the elements above-and-to-the-left and
// above-and-to-the-right.
for (int j = 1; j < rowNum; j++) {
row.add(prevRow.get(j-1) + prevRow.get(j));
}
// The last row element is always 1.
row.add(1);
triangle.add(row);
}
return triangle;
}
方法二:
public static List<List<Integer>> method2(int nums){
List<List<Integer>> list = new ArrayList<>();
for(int i = 0;i<nums;i++){
List<Integer> inerList = new ArrayList<>();
for(int j=0;j<=i;j++){
if(j == 0 || i==j){
inerList.add(1);
}else{
inerList.add(list.get(i-1).get(j-1)+list.get(i-1).get(j));
}
}
list.add(inerList);
}
return list;
}
4、最大子序和
题目:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
-----------------动态规则:Javascript--------------------------
var maxSubArray = function(nums) {
let pre = 0, maxAns = nums[0];
nums.forEach((x) => {
pre = Math.max(pre + x, x);
maxAns = Math.max(maxAns, pre);
});
return maxAns;
};
------------分治--------------------------
public int maxSubArray(int[] nums) {
return maxSubArrayDivideWithBorder(nums, 0, nums.length-1);
}
private int maxSubArrayDivideWithBorder(int[] nums, int start, int end) {
if (start == end) {
// 只有一个元素,也就是递归的结束情况
return nums[start];
}
// 计算中间值
int center = (start + end) / 2;
int leftMax = maxSubArrayDivideWithBorder(nums, start, center); // 计算左侧子序列最大值
int rightMax = maxSubArrayDivideWithBorder(nums, center + 1, end); // 计算右侧子序列最大值
// 下面计算横跨两个子序列的最大值
// 计算包含左侧子序列最后一个元素的子序列最大值
int leftCrossMax = Integer.MIN_VALUE; // 初始化一个值
int leftCrossSum = 0;
for (int i = center ; i >= start ; i --) {
leftCrossSum += nums[i];
leftCrossMax = Math.max(leftCrossSum, leftCrossMax);
}
// 计算包含右侧子序列最后一个元素的子序列最大值
int rightCrossMax = nums[center+1];
int rightCrossSum = 0;
for (int i = center + 1; i <= end ; i ++) {
rightCrossSum += nums[i];
rightCrossMax = Math.max(rightCrossSum, rightCrossMax);
}
// 计算跨中心的子序列的最大值
int crossMax = leftCrossMax + rightCrossMax;
// 比较三者,返回最大值
return Math.max(crossMax, Math.max(leftMax, rightMax));
}
5、旋转数组
题目:
给定一个数组,将数组中的元素向右移动 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]
方法一暴力:public class Solution {
public void rotate(int[] nums, int k) {
int temp, previous;
for (int i = 0; i < k; i++) {
previous = nums[nums.length - 1];
for (int j = 0; j < nums.length; j++) {
temp = nums[j];
nums[j] = previous;
previous = temp;
}
}
}
}
方法 2:使用额外的数组public class Solution {
public void rotate(int[] nums, int k) {
int[] a = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
a[(i + k) % nums.length] = nums[i];
}
for (int i = 0; i < nums.length; i++) {
nums[i] = a[i];
}
}
}
方法 3:使用环状替换public class Solution {
public void rotate(int[] nums, int k) {
k = k % nums.length;
int count = 0;
for (int start = 0; count < nums.length; start++) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % nums.length;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
count++;
} while (start != current);
}
}
}
来源:力扣(LeetCode)