Day4-学习内容:
(1)剑指offer
面试题3:数组中重复的数字
拓展:(题目二)不修改数组找出重复的数字
面试题4:二维数组中的查找
(2)Leetcode
例1:判断链表是否含有环
例2:求二叉树的最小深度
(3)2017年腾讯暑期实习
编程题3:n个数组成的二元组差最小和最大的对数
(4)试题广场-校招真题(3道单选)
1.剑指offer
面试题3:数组中重复的数字
正确代码:(已调试通过-牛客网)
class Solution {
public:
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
bool duplicate(int numbers[], int length, int* duplication) {
if(numbers==NULL||length<=0){
return false;
}
for(int i=0;i<length;i++){
if(numbers[i]<0||numbers[i]>length-1){
return false;
}
}
for(int i=0;i<length;i++){
while(i!=numbers[i]){
if(numbers[numbers[i]]==numbers[i]){
*duplication=numbers[i];
return duplication;
}
else{
int temp=numbers[i];
numbers[i]=numbers[temp];
numbers[temp]=temp;
}
}
}
return false;
}
};
题目二:不修改数组找出重复的数字
int getDuplication(const int* numbers,int length){
if(numbers==nullptr||length<=0){
return false;
}
int start=1;
int end=length-1;
while(end>=start){
int middle=((end-start)>>1)+start;
int count=countRange(numbers,length,start,middle);
if(end==start){
if(count>1){
return start;
}
else{
break;
}
}
else{
if(count>middle-start+1){
end=middle;
}
else{
start=middle+1;
}
}
}
return -1;
}
int countRange(const int* numbers,int length,int start, int end){
if(numbers==nullptr||length<=0){
return 0;
}
int count=0;
for(int i=0;i<length;i++){
if(numbers[i]>=start&&numbers[i]<=end){
++count;
}
}
return count;
}
面试题4:二维数组中的查找(已调试通过-牛客网)
bool Find(int target, vector<vector<int> > array) {
if(array.size()!=0){
int row=0;
int column=array[0].size()-1;
while(row<array.size()&&column>=0){
if(target==array[row][column]){
return true;
}
else{
if(target<array[row][column]){
--column;
}
else{
++row;
}
}
}
}
return false;
}
遇到问题:段错误,您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起
case通过率为0.00%
原因: 应修改为:int column=array[0].size()-1;
2.Leetcode
例1:判断链表是否含有环
题目描述:
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
正确解法:(已通过!)
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head) return false;
ListNode *slow=head,*fast=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){
return true;
}
}
return false;
}
};
例2:求二叉树的最小深度
题目描述:Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
思路1:递归法
递归,若为空树返回0;
若左子树为空,则返回右子树的最小深度+1;(加1是因为要加上根这一层,下同)
若右子树为空,则返回左子树的最小深度+1;
若左右子树均不为空,则取左、右子树最小深度的较小值,+1;
正确解法:(已调试通过!)
classSolution {
public:
intrun(TreeNode *root)
{
if(root == nullptr) return0;
if(root->left == nullptr) // 若左子树为空,则返回右子树的最小深度+1
{
returnrun(root->right)+1;
}
if(root->right == nullptr) // 若右子树为空,则返回左子树的最小深度+1
{
returnrun(root->left)+1;
}
// 左右子树都不为空时,取较小值
intleftDepth = run(root->left);
intrightDepth = run(root->right);
return(leftDepth<rightDepth)?(leftDepth+1):(rightDepth+1);
}
};
思路2:
层序更效率更高,因为它不需要去遍历所有的节点,一旦找到一个叶节点,它肯定是最短的。
正确解法:(已调试通过!)
classSolution {
public:
typedefTreeNode* tree;
intrun(TreeNode *root) {
//采用广度优先搜索,或者层序遍历,找到的第一个叶节点的深度即是最浅。
if(! root) return0;
queue<tree> qu;
tree last,now;
intlevel,size;
last = now = root;
level = 1;qu.push(root);
while(qu.size()){
now = qu.front();
qu.pop();
size = qu.size();
if(now->left)qu.push(now->left);
if(now->right)qu.push(now->right);
if(qu.size()-size == 0)break;
if(last == now){
level++;
if(qu.size())last = qu.back();
}
}
returnlevel;
}
};
3.2017年腾讯暑期实习
编程题3:n个数组成的二元组差最小和最大的对数
题目描述:
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,相差最小的有多少对呢?相差最大呢?
解题思路:
首先把序列排序,然后对相邻元素两两相减,在n-1个差值中找到最小差值,然后输出差值中有多少最小差值就是差最小的对数。
其次,输出序列中最小数的个数和最大数的个数,把它们相乘就是差最大的对数。
存在的问题若遇到 2 2 2 2 这个序列,按照上述方法会输出 1, 16, 显然不对, 考虑到组合,应该输出 6, 6。
所以需要首先判断序列里数字是否都相同,如果相同,直接输出 n*(n-1)//2,
如果不相同,则需要判断序列中有无重复元素,如果有重复元素,数出所有重复元素的个数same_count,算出它们same_count*(same_count-1)//2的和
如果没有重复元素,则可以用上述求差最小的对数的方法求解
差最大的对数仍可以用上述的方法
参考:
https://blog.csdn.net/chengonghao/article/details/51912652
https://blog.csdn.net/qq_34617032/article/details/78604091
https://blog.csdn.net/ajianyingxiaoqinghan/article/details/78540736
正确程序:(已调试通过!)
#include <iostream>
#include <map>
#include <utility>
using namespace std;
// 用一个map来存储输入的数,当存在相同的数时不插入新的数,而是将计数值+1
int main()
{
int num;
while(cin>>num)
{
map<int,int> myMap;
bool flag = false;
for(int i = 0; i < num ; i++)
{
int k ;
cin>>k;
map<int,int>::iterator ite;
ite = myMap.find(k);
if(ite != myMap.end())
{ (*ite).second++;flag = true;}
else
{
myMap.insert(make_pair(k,1));
}
} // end of for 读取输入的数据
map<int,int>::iterator ite = myMap.begin();
int min =0;
int minv = -1;
if(flag) //如果存在相同的数
{
for( ; ite!= myMap.end(); ite++)
{
if((*ite).second > 1)
min += ((*ite).second * ((*ite).second -1 ))/2;
} //最小差元组对数等于所有相等的数构成的元组对
}
else
{
for( map<int,int>::iterator ite2 = (++myMap.begin()); (ite2)!= myMap.end(); ite2++,ite++ )
{
int k = (*(ite2)).first - (*(ite)).first;
if( minv ==-1 || k < minv )
{ min = (*ite).second * (*ite2).second ;
minv = k; }
else if(minv == k)
{
min+= (*ite).second * (*ite2).second;
}
} // end of for 求不存在相等的值时的最小差的元组对数
}// 最小对的个数
int max = (*myMap.rbegin()).second * (*myMap.begin()).second;
//最大差的对数
cout<< min<<" "<<max<<endl;
}
}
4.试题广场-校招真题(3道单选)
例1:字符串www.qq.com所有非空子串(两个子串如果内容相同则只算一个)个数是(D)
A.1024 B.1018 C.55 D.50
解析:注意两个概念:子串与子序列。
子串是从原字符串中连续截取得到的;而子序列则不要求连续,即可以是离散截取的。
如果求的是子序列,那么答案是B. 1018。具体计算是: 2^10 = 1024 个子序列,减去空串1个为1023,再减去子序列长度为1时重复的2个w和1个q为1020,最后再减去子序列长度为2时重复的2个ww,只剩下1018个不重复的子序列。
现在求的是子串,则只有 1 + 2 + 3 + ... + 10 = 55 个,减去重复的两次w,一次q,一次.,一次ww,只剩下 50 个不重复的。(
要求的是子串,从左到右一次截取, 10个字符的子串,1个; 9个字符的子串,2个; 8----------------------3 7----------------------4 ......... 1----------------------10 共有:1+2+3+...+10=10*(10+1)/2=55 减去重复的: 1个字符时有3个w,2个q,2个. 2个字符时有2个ww 故应减去:(2+1+1+1)=5 答案:55-5=50,选D。
例2:希尔 冒泡 快速 插入 哪个平均速度最快?(C)
A.希尔 B.冒泡 C.快速 D.插入
例3:下列说法中错误的是:(C)
A.插入排序某些情况下复杂度为O(n)
B.排序二叉树元素查找的复杂度可能为O(n)
C.对于有序列表的排序最快的是快速排序
D.在有序列表中通过二分查找的复杂度一定是O(log2n)
解析:
有序列表使用快排将达到最坏的情况0(n2)。有序列表最快的是二分查找的复杂度是 O(logN)。
对排序算法进行整理:
简单排序时间复杂度都为O(n2),空间复杂度为O(1),简单排序又包括冒泡(稳定),选择(不稳定),插入(稳定)。但在速度上插入大于选择大于冒泡。
高级排序:希尔排序(基于插入排序), O(N*(logn)2),不稳定;快排最好(O(N*logN))最坏O(n2)--当元素有序时、,空间复杂度为O(logn),不稳定。
堆排序最好最坏都一样(nlogn)但是需要一个辅助存储point,所以空间复杂度为O(1),不稳定。
归并排序最好最坏(nlogn),空间复杂为O(n),稳定。
基数排序最好最坏(O(d(n+rd))),空间复杂为O(rd)不稳定。