数组
删除排序组数中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列
分析:题目给了一个有序数组,证明这个数组是已经排好序的有重复的元素会挨在一起,我们只要给这个数组遍历,让他们两两比较,这考验我们双指针的用法,
双指针
双指针又分为快慢指针和左右指针。其中快慢指针主要用于解决链表问题,而左右指针用于解决数组问题。
快慢指针
顾名思义,快慢指针是指一个指针走的快,一个指针走得慢。
左右指针
左右指针是指双指针中一个指针在数组的最左侧,而另一个在最右侧。通过判断,可以分别让两侧的指针向中间移动,以求解问题
这个题目用的是左右指针,左右指针都在最左边,右指针始终往右移动,如果右指针指向的值等于左指针指向的值,左指针不动,右指针继续往右走,如果右指针指向的值不等于左指针指向的值,那么左指针往右移一步,然后再把右指针指向的值赋给左指针。
class Solution {
public int removeDuplicates(int[] nums) {
//边界值判断
if(nums==null || nums.length ==0)
return 0;
int left = 0;
for(int right=1;right<nums.length;right++){
if(nums[right] != nums[left]){
++left;
nums[left]=nums[right];
}
}
return ++left;
}
}
两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
这道题我同样想到的是双指针,左右指针,遍历循环进行相加判断。
class Solution {
public int[] twoSum(int[] nums, int target) {
int left = 0;
int right=1;
while(nums[left]+nums[right] != target){
if(right == nums.length-1){
left++;
right=left;
}
right++;
}
return new int[]{left,right};
}
}
旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
提示:
n == matrix.length == matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
这道题考验的是二维数组和数学中的矩阵,先看看普通的矩阵怎么写
public class ArrayText {
public static void main(String[] args) {
int [][] matrix={{1,2,3},{4,5,6},{7,8,9}};
for(int i=0; i<3; i++){
for (int j=0; j<3; j++)
System.out.printf("%-5d",matrix[i][j]);
//"%md":输出格式为整形,长度为m(输出最小长度),左对齐
System.out.println();
}
System.out.println("**************************************************");
// rotate(matrix);
}
}
里面的 i 表示的是行 j 表示的是列
题目的解决方法有好多,我脑子比较笨 ,刚开始学习,所以只会一点点办法,
class Solution {
public void rotate(int[][] matrix) {
//先上下对折,在按着斜对角线对折
//上下交换 i表示的是行 matrix.length-i-1表示的是上下对折的相对应的下标
for (int i =0;i<matrix.length/2;i++){
int temp[]= matrix[i];
matrix[i]=matrix[matrix.length-i-1];
matrix[matrix.length-i-1]=temp;
}
//在按照对角线交换
for (int i = 0; i < matrix.length; ++i) {
for (int j = i + 1; j < matrix.length; ++j) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
}
旋转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [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]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
我一开始觉得双指针比较容易,写了以后发现出现了数组越界的问题请看代码
public static void main(String[] args) {
int[] nums = new int[]{1,2,3,4,5,6,7};
int k = 3;
ArrayText p = new ArrayText();
p.rotate(nums, k);
System.out.println(Arrays.toString(nums));
}
public void rotate(int[] nums, int k) {
int left = 0;
int right = nums.length-k;
int[] arr = new int[nums.length];
while (right < nums.length) {
arr[left++] = nums[right++];
}
for (int i = 0; i < nums.length-k; i++) {
arr[left] = nums[i];
left++;
}
System.arraycopy(arr,0,nums,0,nums.length);
return;
}
在idea里面没有什么问题,但是提交的时候出现了问题
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 1
at line 7, Solution.rotate
at line 54, __DriverSolution__.__helper__
at line 87, __Driver__.main
但是我没有发现怎么改,所以就有借鉴了一下其他大佬的写法是一种递归加上双指针的写法,很简单理解的
class Solution {
public void rotate(int[] nums, int k) {
k%=nums.length;
int left=0;
int right=nums.length-1;
// 第一轮翻转
reverse(nums, left, right);
//第二轮翻转是[0,k-1]
reverse(nums, left, k-1);
// 第三轮翻转是[k,right]
reverse(nums, k, right);
}
//双指针进行翻转数组
public void reverse(int [] nums,int left,int right) {
while(left<right) {
int temp=nums[left];
nums[left]=nums[right];
nums[right]=temp;
left++;
right--;
}
}
}
https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2gy9m/