双指针算法
图形
题目一
描述:
提取字符串中 用 单个空格隔开的单词
输入:
i am boy;
输出:
i
am
boy
代码实现
import java.io.BufferedReader;import java.io.InputStreamReader;public class ForSubstring {public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] strs = br.readLine().split("");String str;for (int i = 0; i < strs.length; i++) {int j = i;while( j < strs.length && !" ".equals(strs[j])) j ++;for (int k = i; k < j; k++) {System.out.print(strs[k]);}System.out.println();i = j;}}}
题目二
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼1e5 范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1≤n≤1e5
输入样例:
5 1 2 2 3 5
输出样例:
3
代码实现:
//hashmap 实现for ( int i = 0,j = 0; i < n;i ++) {while(map.containsKey(arr[i])) map.remove(arr[j++]);map.put(arr[i],1);res = Math.max(map.size(),res);}//数组实现 比hashmap快for ( int i = 0,j = 0 ; i < n;i ++) {b[arr[i]] ++ ;while (b[arr[i]] > 1) b[arr[j++]] --;res = Math.max(res,i-j+1);}
题目三
题目描述
给定两个升序排序的有序数组 A 和 B,以及一个目标值 x。
数组下标从 0 开始。
请你求出满足 A[i]+B[j]=x 的数对 (i,j)。
数据保证有唯一解。
输入格式
第一行包含三个整数 n,m,x,分别表示 A 的长度,B 的长度以及目标值 x。
第二行包含 n 个整数,表示数组 A。
第三行包含 m 个整数,表示数组 B。
输出格式
共一行,包含两个整数 i 和 j。
数据范围
数组长度不超过 105。
同一数组内元素各不相同。
1≤数组元素≤109
输入样例:
4 5 6
1 2 4 7
3 4 6 8 9
输出样例:
1 1
代码实现:
int n = Integer.parseInt(strs[0]),m = Integer.parseInt(strs[1]),x = Integer.parseInt(strs[2]);int[] a = new int[n];int[] b = new int[m];strs = br.readLine().split( " ");String[] strings = br.readLine().split( " ");Map<Integer,Integer> map = new HashMap<>();//因为n与m可大可小,所以有个取最大值//只要i < n 就可以处理a数组//只要i < m 就可以处理b数组//以a数组为例 存入mapfor (int i = 0; i < (n > m ? n : m) ; i++) {if (i < n) {a[i] = Integer.parseInt(strs[i]);map.put(a[i],i);}if (i < m) b[i] = Integer.parseInt(strings[i]);}//循环判断,只要x - b[i] 存在于map中 即为所得for (int i = 0; i < m; i++) {if (map.containsKey(x-b[i])) System.out.println(map.get(x-b[i])+" "+i);}}
题目四
给定一个长度为 nn 的整数序列 a1,a2,…,an以及一个长度为 m 的整数序列 b1,b2,…,bm。
请你判断 a 序列是否为 b 序列的子序列。
子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5}是序列 {a1,a2,a3,a4,a5}的一个子序列。
输入格式
第一行包含两个整数 n,m
第二行包含 nn 个整数,表示 a1,a2,…,an
第三行包含 mm 个整数,表示 b1,b2,…,bm
输出格式
如果 a 序列是 b 序列的子序列,输出一行 Yes。
否则,输出 No。
数据范围
1≤n≤m≤105
−109≤ai,bi≤109
输入样例:
3 5
1 3 5
1 2 3 4 5
输出样例:
Yes
代码实现:
for (int i = 0; i < m ; i++) {if (i < n) a[i] = Integer.parseInt(strs[i]);if (i < m) b[i] = Integer.parseInt(strings[i]);}int j = 0;for (int i = 0; i < m; i ++) {if (b[i] == a[j]) j++;if(j == n) {System.out.println("Yes");break;}if(i == m -1 ) System.out.println("No");}
位运算
求 n 的第 k 位数 n >> k & 1 ;
返回n的最后一位1 lowbit( n ) = n & (-n)
题目
给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。
输入格式
第一行包含整数 n。
第二行包含 n个整数,表示整个数列。
输出格式
共一行,包含 n 个整数,其中的第 i 个数的二进制表示中 1 的个数。
数据范围
1≤n≤100000
0≤数列中元素的值≤109
输入样例:
5
1 2 3 4 5
输出样例:
1 1 2 1 2
代码实现:
int i = 0;while (n-- != 0) {int res = 0;while(arr[i] != 0) {arr[i] -= (arr[i] & -arr[i]);res++;}i++;System.out.print(res+" ");}
离散化
图形
题目
题目描述
假定有一个无限长的数轴,数轴上每个坐标上的数都是00。
现在,我们首先进行nn次操作,每次操作将某一位置 xx 上的数加 cc 。
接下来,进行 mm 次询问,每个询问包含两个整数 ll 和 rr,你需要求出在区间 [l,r][l,r] 之间的所有数的和。
输入格式
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109−109≤x≤109
1≤n,m≤1051≤n,m≤105
−109≤l≤r≤109−109≤l≤r≤109
−10000≤c≤10000−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
代码实现:
import java.io.*;import java.util.*;public class Main {final static int N = 300100;public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] strs = br.readLine().split(" ");int n = Integer.parseInt(strs[0]),m = Integer.parseInt(strs[1]);int[] q = new int[N];int[] s = new int[N];List<Integer> alls = new ArrayList<>();List<Node> add = new ArrayList<>();List<Node> query = new ArrayList<>();for (int i = 0; i < n; i++) {strs = br.readLine().split(" ");int x = Integer.parseInt(strs[0]);int c = Integer.parseInt(strs[1]);add.add(new Node(x,c));alls.add(x);}for (int i = 0; i < m; i++) {strs = br.readLine().split(" ");int l = Integer.parseInt(strs[0]);int r = Integer.parseInt(strs[1]);alls.add(l);alls.add(r);query.add(new Node(l,r));}Collections.sort(alls);int unique = unique(alls);alls = alls.subList(0,unique);for (Node node : add) {int index = find(node.first,alls);q[index] = 0;q[index] += node.last;}for (int i = 1; i <= alls.size(); i++) s[i] = s[i - 1] + q[i];for (Node node : query) {int l = find(node.first,alls);int r = find(node.last,alls);System.out.println(s[r] - s[l - 1]);}br.close();}private static int unique(List<Integer> list) {int j = 0;for (int i = 0; i < list.size() - 1; i++) {if(i == 0 || list.get(i) != list.get(i - 1)) {list.set(j,list.get(i));j++;}}return j;}private static int find (int x ,List<Integer> list) {int l = 0;int r = list.size() - 1;while (l < r) {int mid = l + r >> 1;if (list.get(mid) >= x) r = mid;else l = mid + 1;}return l + 1;}}class Node {public int first;public int last;public Node(int first, int last) {this.first = first;this.last = last;}}
区间合并
图形
题目
给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3]和[2,6]可以合并为一个区间[1,6]。
输入格式
第一行包含整数n
接下来n行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1≤n≤100000,
−109≤li≤ri≤109
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
代码实现:
List<Node> megs = new ArrayList<>();while (n-- != 0) {String[] strs = br.readLine().split(" ");int l = Integer.parseInt(strs[0]),r = Integer.parseInt(strs[1]);megs.add(new Node(l,r));}System.out.println(mergeInterval(megs));private static int mergeInterval(List<Node> megs) {megs.sort(new Comparator<Node>() {@Overridepublic int compare(Node o1, Node o2) {return o1.first - o2.first;}});int r = Integer.MIN_VALUE,k = 0;for (Node node : megs) {if(node.first > r) k++;r = r > node.last ? r : node.last;}return k;}

