Oj599:两数之和1
题目描述
给定一个从小到大的数组和一个目标数 t,在其中找到两个数,使得两数之和与目标数相等,输出两个数在数组中的位置。
输入
第一行两个整数 n,t。(1≤n≤1000000,1≤t≤20000000)
接下来一行 n 个数,均小于 10000000。
输出
输出两个用空格隔开的数表示位置(从零开始计数),答案有唯一解。
样例输入
6 15
1 5 6 7 10 26
样例输出
1 4
数据规模与约定
时间限制:1 s
内存限制:256 M
100% 的数据保证 1≤n≤1000000
思路:
注意:数据量大,用cin读入会有超时的风险,采用scanf
三种方法:
1、暴力解:两层循环进行遍历,会超时,时间复杂度O(n^2)
2、固定一个数,另一个用二分的方法去找,时间复杂度O(nlogn)
3、hash表,固定一个数,另一个数从hash表中查找,时间复杂度O(n),空间复杂度O(n)
4、双指针法:时间复杂度O(n)
代码演示(双指针法)
#include<iostream>
#include <cstdio>
using namespace std;
int n, t, num[1000005];
int main(int argc, char *grav[])
{
scanf("%d%d", &n, &t);
for (int i = 0; i < n; i++) {
scanf("%d", &num[i]);
}
int l = 0, r = n - 1;
while (l < r) {
if (num[l] + num[r] == t) {
cout << l << " " << r << endl;
return 0;
}
// 数小于目标,动左指针
if (num[l] + num[r] < t) {
l++;
} else {
r--;
}
}
cout << -1 << endl;
return 0;
}
扩展:
三数之和:固定一个数,剩下两个采用两数之和的方法,时间复杂度O(n^2)
Oj600:杨氏矩阵
题目描述
给定一个 n 行 m 列的二维矩阵和一个目标数 t,二维矩阵中对于每一行从左到右不下降(右边的数大于等于左边的数),对于每一列从上到下不下降(下边的数大于等于上边的数)。现要在数组中找到目标数 t,并输出其所在位置的行数和列数。
注意:本题数据已更新,t 已改为在最后输入,所有不符合要求的提交记录均已被删除。
输入
第一行两个整数 n,m。(1≤n,m≤3000)
接下来一个二维矩阵,矩阵内所有数均小于 200000。
最后一行一个整数 t。(1≤t≤200000)
输出
输出两个用空格隔开的数表示位置(从一开始计数),答案有唯一解。
样例输入
3 4
1 2 3 4
5 6 15 20
7 10 20 25
15
样例输出
2 3
数据规模与约定
时间限制:1 s
内存限制:256 M
100% 的数据保证 1≤n,m≤3000
思路:
时间复杂度为O(n + m)
查找数字可从左下角或右上角的位置进行查找。
- 此问题和两数之和有联系,如下图所示:
代码演示:
#include<iostream>
#include <cstdio>
using namespace std;
int n, m, t, num[3005][3005];
int main(int argc, char *grav[])
{
scanf("%d%d", &n, &m);
// 从(1,1)点开始存
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &num[i][j]);
}
}
// 从左下角开始查找
int x = n, y = 1;
cin >> t;
while (1) {
if(num[x][y] == t) {
printf("%d %d\n", x, y);
return 0;
}
if (num[x][y] > t) {
x--;
} else {
y++;
}
}
cout << -1 << endl;
return 0;
}
Oj479:乒乓球
题目描述
国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中 11 分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白 11 分制和 21 分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。
华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在 11 分制和 21 分制下,双方的比赛结果(截至记录末尾)。
比如现在有这么一份记录,(其中 W 表示华华获得一分,L 表示华华对手获得一分):
WWWWWWWWWWWWWWWWWWWWWWLW
在 11 分制下,此时比赛的结果是华华第一局 11 比 0 获胜,第二局 11 比 0 获胜,正在进行第三局,当前比分 1 比 1。而在 21 分制下,此时比赛结果是华华第一局 21 比 0 获胜,正在进行第二局,比分 2 比 1。如果一局比赛刚开始,则此时比分为 0 比 0。直到分差大于或者等于 2,才一局结束。
你的程序就是要对于一系列比赛信息的输入(WL 形式),输出正确的结果。
输入
每个输入文件包含若干行字符串,字符串有大写的 W、L 和 E 组成。其中 EE 表示比赛信息结束,程序应该忽略 E 之后的所有内容。
输出
输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是 11 分制下的结果,第二部分是 21 分制下的结果,两部分之间由一个空行分隔。
样例输入
WWWWWWWWWWWWWWWWWWWW
WWLWE
样例输出
11:0
11:0
1:1
21:0
2:1
数据规模与约定
时间限制:1 s
内存限制:256 M
100% 的数据保证 每行至多 25 个字母,最多有 2500 行
思路:
首先确定数据范围:
代码演示:
#include<iostream>
#include <cmath>
using namespace std;
int a11[6000][2], a21[3000][2], ind1, ind2;
void p() {
for (int i = 0; i <= ind1; i++) {
cout << a11[i][0] << ":" << a11[i][1] << endl;
}
cout << endl;
for (int i = 0; i <= ind2; i++) {
cout << a21[i][0] << ":" << a21[i][1] << endl;
}
}
int main(int argc, char *grav[])
{
char s[30];
while (cin >> s) {
for (int i = 0; s[i]; i++) {
if (s[i] == 'E') {
p();
return 0;
}
if (s[i] == 'W') {