文章目录
88. 合并两个有序数组
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
方法:双指针加原地覆盖
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m-1;
int j = n-1;
int k = m+n-1;
while (i>=0 && j>=0){
if(nums1[i]<nums2[j]){
nums1[k--] = nums2[j--];
}else{
nums1[k--] = nums1[i--];
}
}
while (j>=0){
nums1[k--] = nums2[j--];
}
}
}
118. 杨辉三角
给定一个非负整数 *numRows,*生成杨辉三角的前 numRows 行。在杨辉三角中,每个数是它左上方和右上方的数的和。
方法:暴力法
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> res = new ArrayList<>();
//杨辉三角的每行
for(int i=0;i<numRows;i++){
//每行是一个ArrayList
List<Integer> list = new ArrayList<>();
//每个ArrayList中存放的元素个数正好等于行数
for(int j=0;j<=i;j++){
//每行的第一个数和最后一个数为1
if(j==0 || j==i) {
list.add(1);
}else{
//每行的其他数为是它左上方和右上方的数的和
list.add(res.get(i-1).get(j)+res.get(i-1).get(j-1));
}
}
res.add(list);
}
return res;
}
}
121. 买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。
方法:动态规划
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0 || prices==null) return 0;
// dp[i][j]代表第i天股票状态为j时,所能获得的最大利润
// j=0:买入股票,j=1:卖出股票
int[][] dp = new int[prices.length][2];
dp[0][0] =-prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[prices.length-1][1];
}
}
122. 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
方法:动态规划
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0 || prices==null) return 0;
//dp[i][j]代表第i天股票状态为j时,所能获得的最大利润
// j=0:买入股票,j=1:卖出股票
int[][] dp = new int[prices.length][2];
dp[0][0] =-prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[prices.length-1][1];
}
}
167. 两数之和 II - 输入有序数组
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
方法:双指针
class Solution {
public int[] twoSum(int[] numbers, int target) {
int index1 = 0;
int index2 = numbers.length-1;
while (index1<index2){
if(numbers[index1]+numbers[index2]==target){
return new int[]{index1+1,index2+1};
}else if(numbers[index1]+numbers[index2]<target){
index1++;
}else{
index2--;
}
}
return new int[]{-1,-1};
}
}
169. 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
int mainNum = 0;
for(int i=0;i<nums.length;i++){
//如果count==0就更新众数
if(count==0){
mainNum = nums[i];
}
if(nums[i]==mainNum){
count++;
}else{
count--;
}
}
return mainNum;
}
}
217. 存在重复元素
给定一个整数数组,判断是否存在重复元素。如果任意一值在数组中出现至少两次,函数返回 true
。如果数组中每个元素都不相同,则返回 false
。
方法:先排序,排序后判断存不存在前后两个数相同,存在就返回true,不存在就返回false
class Solution {
public boolean containsDuplicate(int[] nums) {
if(nums.length==0 || nums==null) return false;
Arrays.sort(nums);
for(int i=1;i<nums.length;i++){
if(nums[i] == nums[i-1]){
return true;
}
}
return false;
}
}
219. 存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
方法1:暴力法
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]==nums[j] &&j-i<=k){
return true;
}
}
}
return false;
}
}
方法2:使用HashSet维持一个长度为k的窗口
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashSet<Integer> set = new HashSet<>();
//维持一个长度为k的窗口
for(int i=0;i<nums.length;i++){
if(set.contains(nums[i])) return true;
set.add(nums[i]);
//如果set集合的长度大于k,移除set集合中最旧的那个元素
if(set.size()>k){
set.remove(nums[i-k]);
}
}
return false;
}
}
268. 丢失的数字
给定一个包含 [0, n]
中 n
个数的数组 nums
,找出 [0, n]
这个范围内没有出现在数组中的那个数。
方法1:先排序,然后看元素下标和元素是否相同,如果不同,就返回数组下标,如果循环结束扔相同,返回n
class Solution {
public int missingNumber(int[] nums) {
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
//[0,1,2,4]
if(nums[i]!=i) return i;
}
//[0,1]
return nums.length;
}
}
方法2:哈希表,将数组中元素都存进hash表中,然后判断[0-n]中的元素哪个没在hash表中
class Solution {
public int missingNumber(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++){
set.add(nums[i]);
}
for(int i=0;i<=nums.length;i++){
if(!set.contains(i)){
return i;
}
}
return -1;
}
}
方法3:位运算
class Solution {
public int missingNumber(int[] nums) {
//异或运算,先把[0,n]之间的数进行位运算,然后在于数组nums中的元素进行位运算,即为最终结果
//比如[0,1,2,4] 先把0^1^2^3^4 再^0^1^2^4 = (0^0)^(1^1)^(2^2)^(4^4)^3=3
int count = nums.length;
for(int i=0;i<nums.length;i++){
count = count ^ i;
}
for(int i=0;i<nums.length;i++){
count = count ^ nums[i];
}
return count;
}
}