目录
一、数组
1.1删除排序数组中的重复项
题目描述:给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。将最终结果插入 nums 的前 k 个位置后返回 k 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2gy9m/
分析:
设定left = 0;从下标1开始逐个遍历nums中的各个数值,并判断该数值是否与前面的数值相等;相等时,直接跳过;不相等是,left++;再添加到nums[left] 当中.最后返回的是删除重复数字后数组的长度,即left+1
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0||nums == null){
return 0;
}
//int count = 0;
int left = 0;
for(int i = 1;i<nums.length;i++){
if(nums[left] != nums[i]){
left++;//左指针右移
nums[left] = nums[i];
}
}
return left+1;
}
}
1.2买卖股票最佳时机
题目描述:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2zsx1/
分析:后一天的股价减去前一天的股价,若为正数则添加到利润当中,若为负数则直接跳过
class Solution {
public int maxProfit(int[] prices) {
int profit = 0;
for(int i = 1; i<prices.length;i++){
if(prices[i]-prices[i-1] > 0){
profit += prices[i]-prices[i-1];
}
}
return profit;
}
}
1.3旋转数组
题目描述:给你一个数组,将数组中的元素向右轮转 `k` 个位置,其中 `k` 是非负数。
分析:写一个反转函数,即第一个反转到最后一个,倒数第一个反转到第一个,依次类推。再掉用该函数,先进行全部反转,然后再将反转后的前k个进行反转,最后将后面的n-k个数组进行反转即可。
class Solution {
public void rotate(int[] nums, int k) {
/*int hold = nums[0];
int temp = 0;
int index = 0;
boolean isVisited[] = new boolean[nums.length];
for(int i = 0;i < nums.length;i++){
index = (index + k)%nums.length;
if(isVisited[index]){
index = (index + 1)%nums.length;//已经访问过了,直接从下一个元素开始
hold = nums[index];
i--;
}else{
//当前值保留到下一位置,保存之前把下一位置的值保存到temp;
isVisited[index] = true;
temp = nums[index];
nums[index] = hold;
hold = temp;
}
}*/
k = k % nums.length;
reverse(nums,0,nums.length-1);
reverse(nums,0,k-1);
reverse(nums,k,nums.length-1);
}
public void reverse(int[] nums,int begin,int end){
while(begin < end){
int temp = nums[begin];
nums[begin++] = nums[end];
nums[end--] = temp;
}
}
}
1.4存在重复元素
题目描述:给你一个整数数组 `nums` 。如果任一值在数组中出现 至少两次,返回 `true` ;如果数组中每个元素互不相同,返回 `false` 。
分析: 使用set特性,集合中的元素不能有重复的。将数组中的元素添加到set集合当中,再比较原数组的长度与set集合的长度。
class Solution {
public boolean containsDuplicate(int[] nums) {
//存在HashSet当中,不允许有重复的值
HashSet<Integer> temp = new HashSet<Integer>();
for(int i = 0;i<nums.length;i++){
temp.add(nums[i]);
}
//比较temp与nums的长度,如果相等则返回false,否则返回true
if(temp.size() == nums.length){
return false;
}else{
return true;
}
}
}
1.5只出现一次的数字
题目描述:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x21ib6/
分析:
方法1:先对原数组进行排序处理,然后比较相邻两个元素。若相等即nums[i-1]==nums[i],则继续循环 i = i+2
不同则返回nums[i-1].
方法2:将数组中的元素保存到HashSet当中,并判断能否加入。如果加入不了,则说明之前存入过,该值为重复值将其移除。最后剩下的为只出现一次的数字。
class Solution {
public int singleNumber(int[] nums) {
//方法1:先进行排序,比较相邻的两个
/*Arrays.sort(nums);
int temp = nums[0];
for(int i = 1; i<nums.length;i = i+2){
if(nums[i-1] != nums[i]){
temp = nums[i-1];
break;
}
}
return temp;*/
//保存到HashSet当中,如果加入不了则说明之前存入过是重复值将其移除。
//最后剩余的为只出现一次的数字。
HashSet<Integer> set = new HashSet<Integer>();
for(int num : nums){
//如果加入不了,说明之前已经保存进去了,为重复值,移除
if(!set.add(num)){
set.remove(num);
}
}
return (int)set.toArray()[0];
}
}
1.6两个数组的交集
题目描述:给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
链接:力扣
分析:先对两个数组进行排序,分别使用两个指针指向数组开始的位置。如果两个指针指向的值相同,则为他们的交集,将该值加入到list集合当中,然后两个指针都向后移一个。如果指针指向的值不同,则指向的值小的指针后移,然后进行比较,直到其中一个指针移动到了末尾则结束。最后返回list集合。
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
List<Integer> list = new ArrayList<>();
int i = 0;//指针1
int j = 0;//指针2
while(i<nums1.length && j<nums2.length){
//两个指针指向的值相等
if(nums1[i] == nums2[j]){
list.add(nums1[i]);
i++;
j++;
}else if(nums1[i] < nums2[j]){
//两个指针指向的不相等时
i++;
}else {
j++;
}
}
int index = 0;
int[] res = new int[list.size()];
for(int k = 0;k < list.size();k++){
res[index++] = list.get(k);
}
return res;
}
}
1.7加1
题目描述:给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2cv1c/
分析:从数组的末尾不为9,直接加1
特殊情况:末尾为9时,加1之后变为0,前一位再加1,在进行判断。
class Solution {
public int[] plusOne(int[] digits) {
for(int i = digits.length -1;i>=0;i--){
if(digits[i] != 9){
digits[i] += 1;//元素不为9,直接加1返回
return digits;
}else{
digits[i] = 0;//元素为9,需要置为0
}
}
//能够到达这里,说明数组中所有的元素均为9.例如999,则需返回1000
int[] temp = new int[digits.length+1];
temp[0] = 1;
return temp;
}
}
1.8移动0
题目描述:给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
分析:从头开始遍历,非0的数值往前挪。
class Solution {
public void moveZeroes(int[] nums) {
int index = 0;
for(int i = 0;i<nums.length;i++){
//非零数字往前挪
if(nums[i] != 0){
nums[index++] = nums[i];
}
}
//非零数字挪完之后,后面全部置为0
while(index < nums.length){
nums[index++] = 0;
}
}
}
1.9两数之和
题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。 链接:力扣
分析:设定两个指针,第一个指针从0开始,第二个指针从第一个指针的下一个进行遍历;寻找出两个指针对应数值相加等于target
将两个指针存入到res数组当中,返回res即可。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
for(int i = 0;i<nums.length;i++){
for(int j = i+1;j<nums.length;j++){
if(nums[i] + nums[j] == target){
res[0] = i;
res[1] = j;
}
}
}
return res;
}
}
1.10有效的数独
题目描述:请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意:
一个有效的数独(部分已被填充)不一定是可解的。 只需要根据以上规则,验证已经填入的数字是否有效即可。 空白格用 '.' 表示。
链接:力扣
分析:判断数独是否有效,只需要判断同一行、同一列以及同一个3*3的小宫格内部不能存在相同的数值
创建3个9*9的布尔类型数组,分别表示行、列和3x3的小宫格。判断其内部是否存在重复的数字,如果存在直接返回false。
class Solution {
public boolean isValidSudoku(char[][] board) {
boolean[][] line = new boolean[9][9];//标记行
boolean[][] colum = new boolean[9][9];//标记列
boolean[][] cell = new boolean[9][9];//标记3*3的小宫格
for(int i = 0;i<board.length;i++){
for(int j = 0;j<board[0].length;j++){
//不为数字,直接跳过
if(board[i][j] == '.'){
continue;
}
int num = board[i][j]-'0'-1;//对应的数值
int k = i/3*3+j/3;//表示第几个小宫格
//判断当前行、列和小宫格是否有相同的数值
if(line[i][num] || colum[j][num] || cell[k][num]){
return false;
}
line[i][num] = true;
colum[j][num] = true;
cell[k][num] = true;
}
}
return true;
}
}
1.11旋转图像
题目描述:给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 链接:力扣
分析:先进行上下对调,即第一行与最后一行进行对调;倒数第二行与第二行进行对调,以此类推。再进行对角线对调。
class Solution {
public void rotate(int[][] matrix) {
//先将第一行和最后一行进行对调,上下对调
for(int i = 0;i<matrix.length/2;i++){
int temp[] = matrix[i];
matrix[i] = matrix[matrix.length-1-i];
matrix[matrix.length-1-i] = temp;
}
//再进行对角线对调
for(int i = 0;i<matrix.length;i++){
for(int j = i+1;j<matrix[0].length;j++){
int num = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = num;
}
}
}
}