【算法】位运算 | 双指针算法

4 阅读2分钟

位运算

求n的第k位数字

  1. 先把第k位移到最后一位 => n>>k

  2. 看 个位 是几 => x&1 (奇数=>1 ;偶数=>0;只保留当前数的最低位)

eg: n=10 => 1010

kn >> k(二进制)n >> k & 1(结果)输出字符
31010 >> 3 = 00010001 & 1 = 11
21010 >> 2 = 00100010 & 1 = 00
11010 >> 1 = 01010101 & 1 = 11
01010 >> 0 = 10101010 & 1 = 00
#include<iostream>
using namespace std;
int main()
{
    int n=10;
    for(int k=3;k>=0;k--) cout<<(n>>k&1);
    return 0;
}

二进制中1的个数

返回n的最后一位1:lowbit(n) = n & -n

-n = ~n+1 // n取反+1

x = 1010 ... 100 ... 0

~x = 0101 ... 011 ...0

~x+1 = 0101 ... 100 ... 0

x&(~x+1) = 0000 ... 100 ... 0

eg:

  1. x=1010 => lowbit(x) = 10
  2. x=10100 => lowbit(x) = 1000
#include<iostream>
using namespace std;

int lowbit(int x)
{
    return x & -x;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        int res = 0;
        while(x)
        {
            x -= lowbit(x); // 每次减去x的最后一位 1
            res++; 
        }
        cout<<res<<' ';
    }
    return 0;
}

双指针算法

常见问题分类:

(1) 对于一个序列,用两个指针维护一段区间

(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

结题模板:

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}

最长连续不重复子序列

#include <iostream>
using namespace std;

const int N = 100010;

int n;
int q[N], s[N];

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    int res = 0;
    for (int i = 0, j = 0; i < n; i ++ )
    {
        s[q[i]] ++ ;
        while (j < i && s[q[i]] > 1) 
        {
            s[q[j]] --;
            j++;
        }
        res = max(res, i - j + 1);
    }

    cout << res << endl;

    return 0;
}

数组元素的目标和

#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int n, m, x;
int a[N], b[N];

int main()
{
    scanf("%d%d%d", &n, &m, &x);
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
    for (int i = 0; i < m; i ++ ) scanf("%d", &b[i]);

    for (int i = 0, j = m - 1; i < n; i ++ )
    {
        while (j >= 0 && a[i] + b[j] > x) j -- ;
        if (j >= 0 && a[i] + b[j] == x) cout << i << ' ' << j << endl;
    }

    return 0;
}