cpp双指针

双指针

在归并排序和快速排序中均有使用,常用的方法:

  • 分别指向2个队列
  • 分别指向1个队列的首尾

其作用是显而易见的,普通的方法可能要遍历2个数组,即O(n^2),但双指针算法总是小于2n,即O(n)的复杂度

给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。

**输入:** s = "abcabcbb" 

**输出:** 3 

**解释:** 因为无重复字符的最长子串是 `"abc"`,所以其长度为 3。

这题写了很久,第一次做很久都没能通过。我的第一反应的想法就是双循环遍历,但即使是最简单的方法也老是出问题。

双循环(me):

int lengthOfLongestSubstring(string s) {  
    /* 在字符串不为空的情况下,答案至少是为1的,下面没写好,所以为了图方便这里直接这么做了 */  
    int max = 1;  
    if(s.size() == 0){  
        max = 0;  
    }  
    for(int i = 0; i < s.size(); i++){  
        for(int j = i + 1; j < s.size(); j++){  
            for(int k = i; k < j; k++){  
                /**/  
                if(s[k] == s[j]){  
                    if(j - i > max){  
                        max = j - i;  
                    }  
                    /* 希望退出2层循环,但不想用goto,自己想的小trick */  
                    j = s.size() + 10;  
                    break;                }  
            }  
            /* 针对j一直走到头的情况 */  
            if(j == s.size()-1){  
               if(j - i + 1> max){  
                   max = j - i + 1;  
               }  
            }  
        }  
    }  
    return max;  
}

显然,这个方法时间复杂度是O(n2),如果算上中间的查重步骤,复杂度可能到了O(n3)

下面用双指针来实现,用一个数组b来判重,

int lengthOfLongestSubstring(string s) {
	
    int b[128] = {0};  
    int max = 0;
    /**  
	 * i在左边,j在右边
	 * j向前进的过程中每当遇到一个字符,就会去b这个字典里面对其出现的次数+1
	 * 而当b中对应的大小大于1时,说明其出现了不止一次,则要i从左向右边移动,去掉这个重复的字符
	 * 当j不断向右移动的过程中,i也总是向右移动的(j向右移动,i能向左移的话,说明前一个i的位置是错误的)
	 * 这样的单调性简化了算法
	 * 如何说明这样的过程是没有遗漏的呢?
	 * */  
    for(int i = 0, j = 0; j < s.size(); j++) {  
        b[s[j]]++;  
        while(b[s[j]] > 1) {  
            b[s[i]]--;  
            i++;  
        }  
        max = std::max(max, j - i + 1);  
    }  
    return max;  
}

上一种做法耗时264ms,下一种做法耗时4ms,无论是代码量还是效率都完全的碾压了。

快慢指针

![[Pasted image 20231214173255.png]]

简而言之就是一个指针快,一个指针慢,用于确定一个区间范围

for(i = 0, j = 0; j < nums.size(); j ++){
	if(nums[j] != val){
		nums[i ++] = nums[j];
	}
}
return i;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值