经典数据结构和算法

结构之法 算法之道

1。在无序数组中找最大的K个数?
2。对无序数组A[0:n-1]进行预处理(不能改变A[0:n-1]内元素的顺序),使得能在O(1)时间内快速找到子数组A[i:j]的和?
3。在一个单向链表中实现快排?
4。写一个汉诺塔问题,打印出转移路径?
5。写一个二叉树前序遍历的代码?
6。写一个多叉树实现,并层次遍历的代码?
7。一个字母组成的字符串,对该字符串字母序进行排序,大写在小写前面,时间复杂度O(n),如AaB是有序的,ABa是无序的。
8。第二道题计算f(x,n)=x+x^2+…..+x^n,要求乘法次数最少。
9。两个长度为n的排好序数组,计算中位数(如何证明)。
10。一个大文件,里面是很多字符串,用最优的方式计算出一个字符串是否存在。
11。抛硬币正反面概率一个1/3,一个2/3,设计一个随机数生成器以1/2概率生成1,改为1/n如何设计?
12。一个排好序的1,2,….n的数组,其中一个数变为-1,如何找到这个数,至少用三中方法。
13。mysql索引相关的知识,索引在什么情况下失效
14。把一个数组中奇数放前面,偶数放后面,这个要求写出来。
15。在一个是3亿条IP中,怎么找到次数出现最多的5000条IP。
16。在一组排序数中,给定一个数,返回最接近且不大于这个数的位置,要求时间在O(logn)
(参考:C++中lower_bound函数和upper_bound函数)
lower_bound算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。
upper_bound算法返回一个非递减序列[first, last)中第一个大于val的位置。
有序数组中重复数据的二分查找输出最小的下标,优化一下降低最坏情况的复杂度。
17。找n以内的素数, 判定一个数是否为素数,为什么?
18。手写AVL树的插入算法
19。什么指针数组和数组指针,虚函数,多态实现等等(c++)
20。计算一个int里面二进制有几个1,(n=n&n-1)
21。深度优先、广度优先算法
22。排序算法及对应的时间复杂度和空间复杂度
23。查找算法
24。B+树和二叉树查找时间复杂度
25。KMP算法、hash算法
26。常用的hash算法有哪些
27。如何判断一个单链表是否有环?
28。给你一万个数,如何找出里面所有重复的数?用所有你能想到的方法,时间复杂度和空间复杂度分别是多少?
29。给你一个数组,如何里面找到和为K的两个数?
30。100000个数找出最小或最大的10个?
31。一堆数字里面继续去重,要怎么处理?
32。有25匹马,速度都不同,但每匹马的速度都是定值。现在只有5条赛道,无法计时,即每赛一场最多只能知道5匹马的相对快慢。问最少赛几场可以找出25匹马中速度最快的前3名? (应该是至少7次)

作者:Xoper.ducky
链接:https://www.nowcoder.com/discuss/3043
来源:牛客网
数据结构与算法
1.链表与数组。
2.队列和栈,出栈与入栈。
3.链表的删除、插入、反向。
4.字符串操作。
5.Hash表的hash函数,冲突解决方法有哪些。
6.各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。
7.快排的partition函数与归并的Merge函数。
8.对冒泡与快排的改进。
9.二分查找,与变种二分查找。
10.二叉树、B+树、AVL树、红黑树、哈夫曼树。
11.二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。
12.图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。
13.KMP算法。
14.排列组合问题。
15.动态规划、贪心算法、分治算法。
16.大数据处理:类似10亿条数据找出最大的1000个数………等等
算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。
推荐书籍:《大话数据结构》《剑指offer》《编程之美》
《编程之美》
2.5在n个无序数组中选择最大的K个数(n>=10^8).
2.6精确表达浮点数(参见书本)
2.7求两个正整数的最大公约数(GCD),如果两个正整数都很大,有什么简单的算法吗?
比如,给定两个数a=1100100210001, b = 120200021,求a和b的最大公约数。
2.9 斐波那契数列:
f(0) = 0, f(1) = 1 对于n>1 f(n) = f(n-1) + f(n-2) 求第n项的值? 初了普通的有更加高效的算法吗?
2.10 寻找无序数组中的最大值和最小值,要求计算最少的次数。
2.11给定N个点的二位坐标平面上,寻找最近公共点对?
2.12快速寻找满足条件的两个数
给定一个数组,让这两个数之和等于一个给定的值,为了简单起见,我们假设这个数组中肯定存在至少一组要求的解。
比如:a[] = {5, 6, 1, 4, 7, 9, 8} sum = 10
2.13 子数组的最大乘积?给定N个整数,计算任意(N-1)个数的组合中乘积最大的一组,并写出时间复杂度。
2.14 求数字的子数组之和的最大值(一维数组)?
2.15 求数字的子数组之和的最大值(二维数组)?
2.16 求数组中最长递增子序列的长度?
比如:a [] = {1, -1, 2, -3, 4, -5, 6, -7} 最长为4(1, 2, 4, 6)
2.17 数组循环移位
2.18 数组分割
有一个无须,元素个数为2n的正整数数组,要求:如何能把这个数组分割为元素个数为n的两个数组,并使两个子数组的和最近?
比如 a[] = {1, 5, 7, 8, 9, 6, 3, 11, 20, 17 }
b[] = {1, 3, 11, 8, 20}, c[] = {5, 7, 9, 6, 17}
2.19区间重合判断
给定一个源区间[x, y](y >= x) 和 N个无序目标区间[x1, y1], [x2, y2], [x3,y3]…[xn, yn] 判断源区间[x, y] 是不是在目标区间内?
校园招聘笔试题目:
拼凑钱币
时间限制:1秒
空间限制:32768K
给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0~10000的非负整数)的不同组合的个数。
输入描述:
输入包括一个整数n(1 ≤ n ≤ 10000)
输出描述:
输出一个整数,表示不同的组合方案数
最长公共连续子串
时间限制:1秒
空间限制:32768K
给出两个字符串(可能包含空格),找出其中最长的公共连续子串,输出其长度。
输入描述:
输入为两行字符串(可能包含空格),长度均小于等于50.
输出描述:
输出为一个整数,表示最长公共连续子串的长度。
堆砖块
小易有n块砖块,每一块砖块有一个高度。小易希望利用这些砖块堆砌两座相同高度的塔。
为了让问题简单,砖块堆砌就是简单的高度相加,某一块砖只能使用在一座塔中一次。
小易现在让能够堆砌出来的两座塔的高度尽量高,小易能否完成呢。
输入描述:
输入包括两行:
第一行为整数n(1 ≤ n ≤ 50),即一共有n块砖块
第二行为n个整数,表示每一块砖块的高度height[i] (1 ≤ height[i] ≤ 500000)
输出描述:
如果小易能堆砌出两座高度相同的塔,输出最高能拼凑的高度,如果不能则输出-1.
保证答案不大于500000。
输入例子:
3
2 3 5
输出例子:
5
问题描述:
一个地区ip段表,10万条记录。
记录格式:
beginIP endIP 地区.
一个用户ip记录文件,300万表记录。
记录格式:
用户 IP
希望查找出每个用户ip所在的地区。怎么做效率高?
16。在一组排序数中,给定一个数,返回最接近且不大于这个数的位置,要求时间在O(logn)
参考链接:http://www.cplusplus.com/reference/algorithm/lower_bound/?kw=lower_bound
(参考:C++中lower_bound函数和upper_bound函数)
lower_bound算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。
upper_bound算法返回一个非递减序列[first, last)中第一个大于val的位置。

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;

void testLower_bound()
{
    int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};
    vector<int> v(myints, myints+8);
    sort(v.begin(), v.end()); /// 10 10 10 20 20 20 30 30
    vector<int>::iterator low, up, noElementIndex;
    low = lower_bound(v.begin(), v.end(), 15);
    up = upper_bound(v.begin(), v.end(), 20);
    noElementIndex = lower_bound(v.begin(), v.end(), 40);
    cout << "lower_bound at posion: " << (low-v.begin()) << endl;
    cout << "upper_bound at posion: " << (up-v.begin()) << endl;
    cout << "no: " << noElementIndex - v.begin() << endl;
}

int lower_boundTest(int *arr, int size, int key)
{
    int first = 0, middle;
    int half, len;
    len = size;
    while(len > 0) {
        half = len >> 1;
        middle = first + half;
        if(arr[middle] < key) {
            first = middle + 1;     //移动middle
            len = len-half-1;       //在右边子序列中查找, 更新len
        }
        else {
            len = half;     //在左边子序列(包含middle)中查找, 更新len
        }
    }
    return first;
}

//接口:排好序的数组的首地址(且只能是首地址),数组的大小size(不是位置),以及要比较的关键词
//返回大于k的最小值,如果找不到,返回的值是size(n)
int upper_boundTest(int *arr, int size, int key)
{
    //len表示元素的个数
    int first = 0, middle;//first表示一段区间的首地址
    int half, len;
    len = size;

    while(len > 0) {//len表示的是要寻找的区间的长度
        half = len >> 1;//右移1位除二
        middle = first + half;
        if(arr[middle] <= key) {//如果不在middle上,那么要在右面的区间上
            first = middle + 1;//不包括middle本身
            len = len-half-1; //其实当len为奇数时是多一位的,其实确实是没有影响的
        }
        else
            len = half; //first + half = middle 故是包括middle的
    }
    return first;
}

void testLower_bound_test()
{
     //int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};
     int myints[] = {1, 2, 3, 4, 5, 7, 9, 10, 12, 13};
     int len = sizeof(myints) / sizeof(int);
     sort(myints, myints+len);
     int low = lower_boundTest(myints, len, 8);
     cout << "lowIndex: " << low << endl;
}

void testUpper_boundTest()
{
     int myints[] = {1, 2, 2, 3, 3, 4, 5, 6};
     int len = sizeof(myints) / sizeof(int);
     sort(myints, myints+len);
     int up = upper_boundTest(myints, len, 2);
     cout << "upperIndex: " << up ;
     if(up >= 0 && up < len) {
        cout << " upperElement: " << myints[up] << endl;
     } else {
        cout << "out of range" << endl;
     }
}

int main()
{
    testLower_bound();
    cout << "*****************" << endl;
    testLower_bound_test();
    cout << "*****************" << endl;
    testUpper_boundTest();
    return 0;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值