编程之旅-Day4

52 篇文章 0 订阅
48 篇文章 0 订阅

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)不稳定。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值