Java 双指针

==

class Solution {

public int[] sortedSquares(int[] nums) {

int n = nums.length;

int[] ans = new int[n];

for(int i = 0,j = n - 1,pos = n - 1;i <= j;){

if(nums[i]*nums[i] > nums[j]*nums[j]){

ans[pos] = nums[i]*nums[i];

i++;

}else{

ans[pos] = nums[j]*nums[j];

j–;

}

pos–;

}

return ans;

}

}

复杂度分析

=====

时间复杂度:O(n)O(n),其中 nn 是数组 \textit{nums}nums 的长度。

空间复杂度:O(1)O(1)。除了存储答案的数组以外,我们只需要维护常量空间。

例题1:

====

题目:

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3

输出: [5,6,7,1,2,3,4]

方法一(自己的菜鸟代码):

class Solution {

public void rotate(int[] nums, int k) {

int n = nums.length;

int[] ans = new int[n];

if(k > n){

k = k%n;

}

for(int i = 0,j = n - 1,pos = n - k,flag = 0;i <= j;){

if(pos <= n - 1){

ans[i] = nums[pos];

pos++;

}else{

ans[i] = nums[flag];

flag++;

}

i++;

}

for(int i = 0;i <= n - 1;i++){

nums[i] = ans[i];

}

}

}

方法二  :数组翻转

操作                                   结果

原始数组1~2~3~4~5~6~71 2 3 4 5 6 7
翻转所有元素  7~6~5~4~3~2~17 6 5 4 3 2 1
翻转 [0, k\bmod n - 1][0,kmodn−1] 区间的元素5~6~7~4~3~2~15 6 7 4 3 2 1
翻转 [k\bmod n, n - 1][kmodn,n−1] 区间的元素 5~6~7~1~2~3~45 6 7 1 2 3 4

该方法基于如下的事实:当我们将数组的元素向右移动 kk 次后,尾部 k\bmod nkmodn 个元素会移动至数组头部,其余元素向后移动 k\bmod nkmodn 个位置。

该方法为数组的翻转:我们可以先将所有元素翻转,这样尾部的 k\bmod nkmodn 个元素就被移至数组头部,然后我们再翻转 [0, k\bmod n-1][0,kmodn−1] 区间的元素和 [k\bmod n, n-1][kmodn,n−1] 区间的元素即能得到最后的答案。

class Solution {

public void rotate(int[] nums, int 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 start, int end) {

while (start < end) {

int temp = nums[start];

nums[start] = nums[end];

nums[end] = temp;

start += 1;

end -= 1;

}

}

}

复杂度分析

时间复杂度:O(n)O(n),其中 nn 为数组的长度。每个元素被翻转两次,一共 nn 个元素,因此总时间复杂度为 O(2n)=O(n)O(2n)=O(n)。

空间复杂度:O(1)O(1)。

例题2:

====

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]

输出: [1,3,12,0,0]

说明:

必须在原数组上操作,不能拷贝额外的数组。

尽量减少操作次数。

思路及解法:


使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。

右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。

注意到以下性质:

左指针左边均为非零数;

右指针左边直到左指针处均为零。

因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。

代码:


class Solution {

public void moveZeroes(int[] nums) {

int left = 0,right = 0;

int n = nums.length;

while(right < n){

if(nums[right] != 0){

swap(nums,left,right);

left++;

}

right++;

}

}

public void swap(int[] nums,int left,int right){

int temp = nums[left];

nums[left] = nums[right];

nums[right] = temp;

}

}

例题3:

====

给定一个已按照 非递减顺序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

示例 1:

输入:numbers = [2,7,11,15], target = 9

输出:[1,2]

解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

示例 2:

输入:numbers = [2,3,4], target = 6

输出:[1,3]

示例 3:

输入:numbers = [-1,0], target = -1

输出:[1,2]

代码:

===

class Solution {

public int[] twoSum(int[] numbers, int target) {

int low = 0;

int high = numbers.length - 1;

while(low < high){

int sum = numbers[low] + numbers[high];

if(sum == target){

return new int[]{low+1,high+1};

}else if(sum < target){

low++;

}else{

high–;

}

}

return new int[]{-1,-1};

}

}

例题4:

====

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

输入:s = [“h”,“e”,“l”,“l”,“o”]

输出:[“o”,“l”,“l”,“e”,“h”]

示例 2:

输入:s = [“H”,“a”,“n”,“n”,“a”,“h”]

输出:[“h”,“a”,“n”,“n”,“a”,“H”]

代码:

===

class Solution {

public void reverseString(char[] s) {

for(int left = 0,right = s.length - 1;left < right;left++,right–){

char temp = s[left];

s[left] = s[right];

s[right] = temp;

}

}

}

例题5:

====

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例:

输入:“Let’s take LeetCode contest”

输出:“s’teL ekat edoCteeL tsetnoc”

代码:

===

class Solution {

public String reverseWords(String s) {

StringBuffer str = new StringBuffer();

int end = s.length();

int length = 0;

while(length < end){

int start = length;//记录每个单词的首位索引

while(length < end && s.charAt(length) != ’ '){

length++;//记录每个单词的长度

}

for(int j = start;j < length;j++){

str.append(s.charAt(length + start - j - 1));//字符串的拼接

}

while(length < end && s.charAt(length) == ’ '){

length += 1;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

金三银四马上就到了,希望大家能好好学习一下这些技术点

学习视频:

大厂面试真题:

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

金三银四马上就到了,希望大家能好好学习一下这些技术点

学习视频:

[外链图片转存中…(img-xxWAiC5P-1713110864236)]

大厂面试真题:

[外链图片转存中…(img-WlslssTt-1713110864236)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值