机试指南第二章-经典入门-查找例题自解

查找:

对于查找问题,有难有易。可能只是直接地对某个数字的查找,也可能涉及搜索等相对难度更大的算法。这里先介绍查找的基础概念和方法。

例 2.9 找 x

AC代码:

#include<cstring>
#include<iostream>

using namespace std;
int num[205];

int main()
{
    int n, m, x;
    memset(num, 0, sizeof(num));
    while (cin >> n)
    {
        bool flag = false;
        for (int i = 0; i < n; i++)
        {
            cin >> num[i];
        }
        cin >> x;
        for (int i = 0; i < n; i++)
        {
            if (num[i] == x)
            {
                cout << i << endl;
                flag = true;
                break;
            }
        }
        if (!flag)cout << -1 << endl;
    }
    return 0;
}

通过此例,我们可以了解一下查找所涉及的几个基本要素。

1.查找空间。也常被称为解空间。所谓查找,就是在该查找空间中找寻符合我们要求的解的过程。在此例中,整个数组包含的整数集就是查找空间。

2.查找目标。我们需要一个目标来判断查找空间中的各个元素是否符合我们的要求,以便判断查找活动是否已经成功。在此例中,即数组中的数字与目标数字是否相同。

3.查找方法。即利用某种特定的策略在查找空间中查找各个元素。不同的策略对查找的效率和结果有不同的影响,所以对于某个特定的问题,我们要选择切实可行的策略来查找解空间,以期事半功倍。在此题中,查找方法即线性地遍历数组。

二分查找 :

二分查找建立在待查找元素排列有序的前提上,例如在一个升序有序的数组中查询某元素。我们以在有序表{1,3,4,5,6,8,10}查找3为例,了解它的查找过程:

1.将查找开始点设为第一个数组元素(1),结束点设为最后一个数组元素(10), 即查找子集为整个搜索空间{1,3,4,5,6,8,10}。

2.然后将起始点和结束点正中间的数与查找目标进行比较,若该中间数字等于目标数字则查找成功,查找结束;若大于查找目标,则说明查找目标只可能存在于查找子集中以该中间数字为界的较小的一半中,则移动查找结束点为该中间数字的前一个数字,即新的查找子集为旧的查找子集中以中间数字为界的较小的一半;若小于查找目标,则相应的得到新的查找子集为旧查找子集中以中间数字为界的较大的一半。在该例中,即目标数字3小于中间数字5,移动查找结束点至中间点(5)的前一个元素(4),新的查找子集为{1,3,4},然后继续步骤2。

3.若在查找过程中出现查找起始点大于查找结束点的情况,则说明查找子集已经为空集,查找失败。否则继续步骤2的查找过程。

用二分查找查找长度为 L 的有序数组,时间复杂度可由原本线性查找的O(L)降低到O(logL)。 

例 2.10 查找学生信息

AC代码:

#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

struct Student
{
    char id[100];//学号
    char name[100];//姓名
    int age;
    char sex[5];//性别
    bool operator < (const Student & A)//方便sort函数排序
    {
        return strcmp(id, A.id) < 0;
    }
}stu[1000];

int main()
{
    int n;
    while (cin >> n)
    {
        for (int i = 0; i < n; i++)
        {
            cin >> stu[i].id >> stu[i].name >> stu[i].sex >> stu[i].age;
        }
        sort(stu, stu + n);
        int t;
        cin >> t;//需要查找t组数据
        while (t-- != 0)
        {
            int ans = -1;//初始化目标下标为-1
            char x[30];
            cin >> x;//待查找学号
            int beg = 0, end = n - 1;//查找起始点和结束点,初始查找子集为整个数组
            while (end >= beg)//查找子集不为空时重复二分查找
            {
                int mid = (beg + end) / 2;//中间点下标
                int tmp = strcmp(stu[mid].id, x);
                if (tmp == 0)
                {
                    ans = mid;
                    break;
                }
                else if (tmp > 0) end = mid - 1;
                else beg = mid + 1;
            }
            if (ans == -1) cout << "No Answer!" << endl;
            else cout << stu[ans].id << " " << stu[ans].name << " " << stu[ans].sex << " " << stu[ans].age << endl;
        }
    }
    return 0;
}

利用二分查找,原本O(n * m)的时间复杂度被优化到O(nlogn(排序) + m * logn),而该复杂度是符合我们要求的。 

在查找某特定元素是否存在以外,二分查找还有另一类非常重要的运用,即定界。思考如下问题,在一个升序有序的数组中,确定一个下标点,使在这个下标点之前(包括该下标点)的数字均小于等于目标数字(该目标数字一定大于等于数组中最小的数字),而数组的其余部分均大于目标数字,我们该如何编写程序。这里给出代码以供参考。

//存在一个升序有序的数组buf,其大小为size,目标数字为target
int beg = 0 , end = size; //初始情况与二分查找一致
while (beg <= end) { //二分循环条件与二分查找一致
    int mid = (beg + end) / 2;
    if (buf[mid] <= target) beg = mid + 1; //符合前一部分数字规定
    else end = mid - 1; //否则
}
int ans = end; //最后,end即为我们要求的数字数组下标,buf[end]为该数字本身 

原文地址:https://www.cnblogs.com/yun-an/p/11028963.html

时间: 2024-08-07 17:50:01

机试指南第二章-经典入门-查找例题自解的相关文章

机试指南第二章-经典入门-贪心例题自解

例2.11 FatMouse's Trade 解题思路 贪心策略.每次都买剩余物品中性价比(即重量价格比)最高的物品,直到该物品被买完或者钱耗尽.若该物品已经被买完,则我们继续在剩余的物品中寻找性价比最高的物品 AC代码 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct Thing { double j;

机试指南第二章-经典入门-Hash的应用自解

Hash的应用: Hash即散列,不像数据结构与算法中讲的各种Hash方法和冲突处理等过多的阐述,以下主要介绍Hash在机试试题解答中的作用. 例2.5 统计同成绩学生人数 Hash解法AC代码:(一般想到的也是这种解法) #include<cstring> #include<iostream> using namespace std; int grade[105]; int main() { int n, m, index; memset(grade, 0, sizeof(gra

《N诺机试指南》(九)查找、贪心、链表问题

1.查找问题: 二分查找: 例题:使用map解决查找问题 代码: #include <bits/stdc++.h> using namespace std; //查找学生信息 struct Student{ string name; string sex; int age; string id; }stu[1005]; int main(){ int n; cin >> n; for(int i=0; i<n; i++){ cin >> stu[i].id >

算法导论(Introduction to Algorithms )— 第二章 算法入门 — 2.1 插入排序

一.插入排序:INSERTION-SORT 1.适用范围: which is an efficient algorithm for sorting a small number of elements. 对于少量元素的排序,插入排序是一种高效的算法. 2.原理: Insertion sort works the way many people sort a hand of playing cards. We start with an empty left hand and the cards

计算机考研机试指南(六) ——栈

机试指南 cha 3 栈的应用 括号匹配问题 1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <queue> 5 #include <stack> 6 #include <math.h> 7 #include <string> 8 #include <string.h> 9 #include <std

第二章 算法入门 合并排序

在第二章中难的算法不多,接下来我会把稍微复杂一点的算法整理一下 #include <iostream> using namespace std; void mergeSort(int *A,int left,int mid,int right) { int *L=new int[mid-left+1]; int *R=new int[right-mid+1]; int i,j; for(i=0;i<mid-left+1;i++) { L[i]=A[left+i]; } for (j=0;

Hadoop权威指南---第二章MaxTemperature例题源码

敲了一下hadoop权威指南第二章的例题,虽然基本上是照着书上敲的,但还是把它放到这方便以后查看. 代码如下: <span style="font-size:18px;"><span style="font-size:18px;">import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration;

第二章Python入门

第二章 Python入门 2.1.简介 Python是著名的"龟叔"(Guido van Rossum)在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言 Python的哲学就是简单优雅,尽量写容易看明白的代码,尽量写少的代码.为我们提供了非常完善的基础代码库,覆盖了网络.文件.GUI.数据库.文本等大量内容, 2.1.1.Python适合开发哪些类型的应用呢? 云计算 机器学习 科学运算 自动化运维 自动化测试 爬虫 数据分析 GUI图形化 Web开发等 2.1.2.P

Kali Linux 无线渗透测试入门指南 第二章 WLAN 和固有的不安全性

第二章 WLAN 和固有的不安全性 作者:Vivek Ramachandran, Cameron Buchanan 译者:飞龙 协议:CC BY-NC-SA 4.0 简介 建筑越高,地基就要打得越深. – 托马斯·坎佩斯 没有什么伟大的东西能在脆弱的基础上构建.在我们的语境中,固有的不安全性之上不能构建出安全. WLAN 在设计上拥有特定的不安全性,它们可被轻易利用,例如,通过封包注入,以及嗅探(能够在很远处进行).我们会在这一章利用这些缺陷. 2.1 回顾 WLAN 帧 由于这本书处理无线方面