有关双指针
1. 移动零(附leetcode.283)
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
方法一:双指针
思路:
使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。
右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。
注意到以下性质:
1.左指针左边均为非零数;
2.右指针左边直到左指针处均为零。
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
void swap(int *a, int *b) {
int t = *a;
*a = *b, *b = t;
}
void moveZeroes(int *nums, int numsSize) {
int left = 0, right = 0;
while (right < numsSize) {
if (nums[right]) {
swap(nums + left, nums + right);
left++;
}
right++;
}
}
方法二:二次遍历 java实现
思路:
我们创建两个指针i和j,第一次遍历的时候指针j用来记录当前有多少非0元素。即遍历的时候每遇到一个非0元素就将其往数组左边挪,第一次遍历完后,j指针的下标就指向了最后一个非0元素下标。
第二次遍历的时候,起始位置就从j开始到结束,将剩下的这段区域内的元素全部置为0。
class Solution {
public void moveZeroes(int[] nums) {
if(nums==null) {
return;
}
//第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j]
int j = 0;
for(int i=0;i<nums.length;++i) {
if(nums[i]!=0) {
nums[j++] = nums[i];
}
}
//非0元素统计完了,剩下的都是0了
//所以第二次遍历把末尾的元素都赋为0即可
for(int i=j;i<nums.length;++i) {
nums[i] = 0;
}
}
}
方法三:一次遍历
这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点x,然后把所有小于等于x的元素放到x的左边,大于x的元素放到其右边。
这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。
这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针i和j,只要nums[i]!=0,我们就交换nums[i]和nums[j]
class Solution {
public void moveZeroes(int[] nums) {
if(nums==null) {
return;
}
//两个指针i和j
int j = 0;
for(int i=0;i<nums.length;i++) {
//当前元素!=0,就把其交换到左边,等于0的交换到右边
if(nums[i]!=0) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j++] = tmp;
}
}
}
}
2.反转字符串(附leetcode 344)
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
方法一:双指针
void reverseString(char* s, int sSize){
for (int i = 0, j = sSize - 1; i < j; ++i, --j) {
/* 不断 swap(s[i], s[j]) */
char c = s[i];
s[i] = s[j];
s[j] = c;
}
}
//另一种写法
void reverseString(char* s, int sSize){
int p,q;
p=0;
q=sSize-1;
char temp;
while(p<q){
temp=s[q];
s[q]=s[p];
s[p]=temp;
p++;
q--;
}
}
3.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
//方法一:冒泡排序 注意:会超时
int* sortedSquares(int* nums, int numsSize, int* returnSize){
*returnSize=numsSize;
int j=0;
for(int i=0;i<numsSize;i++){
nums[j++]=nums[i]*nums[i];
}
int temp;
//排序
for(int i=0;i<numsSize;i++){
for(int k=0;k<numsSize-i-1;k){
if(nums[k+1]>nums[k]){
temp=nums[k+1];
nums[k+1]=nums[k];
nums[k]=temp;
}
}
}
return nums;
}
另一种写法:
int* sortedSquares(int* nums, int numsSize, int* returnSize){
*returnSize=numsSize;
int *ans=malloc(sizeof(int)*numsSize);//申请数组空间
for(int i=0;i<numsSize;i++){
ans[i]=nums[i]*nums[i];
}
int temp;
//排序
for(int i=0;i<numsSize;i++){
for(int k=0;k<numsSize-i-1;k){
if(ans[k+1]>ans[k]){
temp=ans[k+1];
ans[k+1]=ans[k];
ans[k]=temp;
}
}
}
return ans;
}
//方法二:双指针
int* sortedSquares(int* a, int n, int* returnSize){
*returnSize=n;
if(n==0) return a;
int p=0,q=-1;
for(int i=0;i<n;i++){
if(a[i]>=0) {
p