面试笔试算法3-Oj刷题

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') {
   
  
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值