java 数据结构 初级算法 (一)

数组

删除排序组数中的重复项

         给你一个 升序排列 的数组 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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值