🏚1.删除排序数组中的重复项
解题思路 使用双指针,首先题目中数组是已经排好顺序的,i为慢指针,j为快指针,如果nums[i]=nums[j]跳过重复项,直到nums[i]!=nums[j],跳过与 i 重复的所有元素,将nums[j]赋值给 i 的下一位nums[i+1],然后递增i,j继续跳过当前 i 的重复项。
代码
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length==0){return 0;}
if(nums.length==1){return 1;}
int i=0;
for(int j=1;j<nums.length;j++){
if(nums[i]!=nums[j]){
nums[i+1]=nums[j];
i++;
}
}
return i+1;
}
}
🏚2.买卖股票的最佳时机
解题思路 将数组中的数字绘制成表格
分析可得,我们需要得到所有的峰值和谷值,最后加起来得到最大利润。因为因为 C 总是小于 A+B
公式:代码
class Solution {
public int maxProfit(int[] prices) {
int i=0;
//定义谷点
int valley = prices[0];
//定义峰点
int peak = prices[0];
//最大利润
int maxmoney = 0;
while(i<prices.length-1){
//找到谷点
while(i<prices.length-1&&prices[i]>=prices[i+1]){i++;}
//得到谷点
valley = prices[i];
//寻找峰点
while(i<prices.length-1&&prices[i]<=prices[i+1]){i++;}
//得到峰点
peak = prices[i];
maxmoney+=peak-valley;
}
return maxmoney;
}
}
🏚3.存在重复元素
解题思路 使用set数组的contains()函数判断传入的key是否出现两次,出现第二次直接返回true
代码
class Solution {
public boolean containsDuplicate(int[] nums) {
HashSet<Integer> set=new HashSet<Integer>();
for(int i=0;i<nums.length;i++){
if(set.contains(nums[i])){return true;}
else{set.add(nums[i]);}
}
return false;
}
}
🏚4.只出现一次的数字
解题思路 首先考虑使用map,遍历一遍数组,将数组的值作为key存入map中,得到value等于1。
更简单的是利用所有数进行异或运算,得到的值为所求的。
代码
class Solution {
public int singleNumber(int[] nums) {
int result=0;
for(int i=0;i<nums.length;i++){
result=result^nums[i];
}
return result;
}
}
🏚5.两个数组的交集 II
解题思路 首先将两个数组中较小的数组存入一个map中,key为数组的元素,value为出现的次数。遍历第二个数组,如果map内存在遍历元素的key,且次数大于1,则将该元素存入结果集中(可以用数组1作为结果集),map内该元素的value减一。
代码
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Map<Integer,Integer> map=new HashMap<>();
for (int i = 0; i <nums1.length ; i++) {
if(map.get(nums1[i])==null){
map.put(nums1[i],1);
}else{
map.put(nums1[i],map.get(nums1[i])+1);
}
}
int k=0;
for (int i = 0; i <nums2.length ; i++){
if(map.get(nums2[i])!=null){
if(map.get(nums2[i])>0){
nums1[k++]=nums2[i];
map.put(nums2[i],map.get(nums2[i])-1);}
}
}
return Arrays.copyOfRange(nums1, 0, k);
}}
🏚6.移动零
解题思路 用双指针,fast指针找不为0的数字,slow指针用来将fast指针找到的数字移动到前面去,最后再last指针的位置加上(fast-last)个0可得。
代码
class Solution {
public void moveZeroes(int[] nums) {
if(nums.length==0||nums.length==1){return;}
int fast=0;
int slow=0;
while(fast<nums.length){
while(nums[fast]==0&&fast<nums.length-1){
fast++;
}
nums[slow]=nums[fast];
slow++;
fast++;
}
for(int i=0;i<(fast-slow);i++){
nums[slow+i]=0;
}
}
}
🏚7.有效的数独
解题思路 分析题目可以得到题目隐含条件:每一行不能出现重复数字,每一列不能出现重复数字,每一个3*3宫格不能出现重复数字,共有九行,九列,九宫格。
我们给每一行,每一列,每一宫格都定义一个map。遍历整个大数组,将当前数字分别放入当前数字所在的行,列,宫格的map中。
判断map中当前数字是否出现过,如果出现过直接返回false,否则返回true。
代码
class Solution {
public boolean isValidSudoku(char[][] board) {
//遍历一遍,首先定义3*9个map 每一行一个(九行),每一列一个(九列),每一宫格一个(九宫格)
HashMap<Integer, Integer> [] rows = new HashMap[9];
HashMap<Integer, Integer> [] columns = new HashMap[9];
HashMap<Integer, Integer> [] boxes = new HashMap[9];
for(int i=0;i<9;i++){
rows[i]=new HashMap<Integer, Integer>();
columns[i]=new HashMap<Integer, Integer>();
boxes[i]=new HashMap<Integer, Integer>();
}
for(int i=0;i<9;i++){//遍历每一行
for(int j=0;j<9;j++){//遍历每一列
char num=board[i][j];//取得当前数字
if(num!='.'){//如果有数字
int n=(int)num;
int box_index = (i / 3 ) * 3 + j / 3;//根据公式求得当前数字所在的宫格序号
rows[i].put(n,rows[i].getOrDefault(n, 0)+1);//将n放入第i行的map中,如果存在则加1
columns[j].put(n,columns[j].getOrDefault(n, 0)+1);//将n放入第j列的map中,如果存在则加1
boxes[box_index].put(n,boxes[box_index].getOrDefault(n, 0)+1);//将n放入序号为box_index宫格的map中,如果存在则加1
if(rows[i].get(n)>1||columns[j].get(n)>1||boxes[box_index].get(n)>1){return false;}
}
}
}
return true;//遍历完成
}
}
🏚8.旋转图像
解题思路 观察可得,旋转矩阵=转置矩阵(行变为列)+翻转矩阵
代码
class Solution {
public void rotate(int[][] matrix) {
//先将矩阵转置,在翻转矩阵
int n=matrix.length;
//转置,将矩阵右上方的元素与右下方交换
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int temp=matrix[i][j];
matrix[i][j]=matrix[j][i];
matrix[j][i]=temp;
}
}
//翻转,轴对称旋转
for(int i=0;i<n;i++){
for(int j=0;j<n/2;j++){
int temp=matrix[i][j];
matrix[i][j]=matrix[i][n-1-j];
matrix[i][n-1-j]=temp;
}
}
}
}