编程之旅-Day6

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

Day6-学习内容:

(1)剑指Offer

面试题10:斐波那契数列

面试题17:打印从1到最大的n位数

(2)leetcode

例1:链表排序

例2:判断链表是否含有环

 

1.剑指Offer

面试题10:斐波那契数列

题目描述:

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0),n<=39。

思路:

(1)递归-大量重复计算、效率低(不可取)

(2)循环实现递归思想-存储中间过程避免重复计算、时间复杂度O(n)(OK)

(3)基于递归的O(n)求n次方-参考面试题16“数值的整数次方”(OK)

代码:c++实现,基于思路(2)(已通过调试!)

class Solution {
public:
    int Fibonacci(int n) {
        if(n>39||n<0){
            return false;
        }
        int f1=0;
        int f2=1;
        int fn=0;
        if(n==0){
            return  f1;
        }
        else if(n==1){
            return f2;
        }
        else{
            for(int i=2;i<=n;i++){
                fn=f1+f2;
                f1=f2;
                f2=fn;
            }
        }
        return fn;
    }
};

总结:加强基于斐波那契数组的应用实践比如“青蛙跳台阶”、“使用2*1的小矩形横竖覆盖更大矩形”等诸多问题。

 

面试题17:打印从1到最大的n位数

题目描述:

输入数字n,按顺序打印出从1到最大的n位十进制数。

思路:

(1)先求出最大的n位数,使用循环逐一打印-没有考虑大数问题,最大n位数可能会造成整型或长整型(long long)溢出(不可取)

(2)字符串上模拟数字加法(可取,但时间有限不好实现)

solution:1.在字符串上模拟加法,用Increment()函数实现

                  2.把字符串表达的数字打印出来

注意点:(1)如何在每次增加1时快速判断当前数字是否达到了最大的n位数,使得时间复杂度O(n).

                  (2)能否按阅读习惯打印出数字,即对于n位数的字符串如何实现从第一个非0字符开始打印。

(3)采用数字排列解法,递归实现(可取,且代码简洁)

代码:C++实现,基于思路(3),书上解法,牛客网上无对应例题故暂未调试。

  1 void Print1ToMaxOfNDigits(int n){
  2      if(n<=0){
  3           return;
  4      }
  5      char *number=new char[n+1];
  6      number[n]='\0';
  7      for(int i=0;i<10;i++){
  8          number[0]= i+'0';
  9          Print1ToMaxOfNDigitsRecursively(number,n,0);
 10      }
 11      delete []numbers;
 12 }
 14 void Print1ToMaxOfNDigitsRecursively(char *number,int length,int index){
 15     if(index==length-1){
 16         PrintNumber(number);
 17         return;
 18     }
 19     for(int i=0;i<10;++i){
 20         number[index+1]=i+'0';
 21         Print1ToMaxOfNDigitsRecursively(number,length,index+1);
 22     }
 23 }
 24 void PrintNumber(char *number){
 25     bool isBeginning0=true;
 26     int nLength=strlen(number);
 27     for(int i=0;i<nLength;++i){
 28          if(isBeginning0&&number[i]!=0){
 29              isBeginning0=false;
 30          }
 31          if(!isBeginning0){
 32              printf("%c",number[i]);
 33          }
 34     }
 35     printf("\t");

参考:https://github.com/zhedahht/CodingInterviewChinese2/blob/master/17_Print1ToMaxOfNDigits/Print1ToMaxOfNDigits.cpp

 

2.Leetcode

例1:链表排序

题目描述:Sort a linked list in O(n log n) time using constant space complexity.

思路:(1)快慢指针+归并排序

           (2)因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。 

归并排序的一般步骤为: 

1)将待排序数组(链表)取中点并一分为二; 

2)递归地对左半部分进行归并排序; 

3)递归地对右半部分进行归并排序; 

4)将两个半部分进行合并(merge),得到结果。 

代码:(已调试通过!)

class Solution {
public:
    ListNode *sortList(ListNode *head) {
        if (!head || !head->next) return head;
         
        ListNode* p = head, *q = head->next;
        while(q && q->next) {
            p = p->next;
            q = q->next->next;
        }
         
        ListNode* right = sortList(p->next);
        p->next = NULL;
        ListNode* left = sortList(head);
         
        return merge(left, right);
    }
     
     
    ListNode *merge(ListNode *left, ListNode *right) {
        ListNode dummy(0);
        ListNode *p = &dummy;
        while(left && right) {
            if(left->val < right->val) {
                p->next = left;
                left = left->next;
            }
            else {
                p->next = right;
                right = right->next;
            }
            p = p->next;
        }
        if (left) p->next = left;
        if (right) p->next = right;
        return dummy.next;
    }
};

例2:判断链表是否含有环

题目描述:

Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull. 

Follow up:
Can you solve it without using extra space? 

思路:

1.首先判断是否存在环
2.若存在环,则从起点开始,每走一步就删除上一个节点的next指针,最后一个节点就是环的起点。因为环的起点会存在两个next指向它。

代码:(已调试通过!)

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head||!head->next){
            return NULL;
        }
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast&&fast->next){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow){
                break;
            }
        }
        if(!fast||!fast->next){
            return NULL;
        }
        ListNode *pre=head;
        ListNode *cur=head->next;
        while(cur){
            if(pre==cur){
                return pre;
            }
            pre->next=NULL;
            pre=cur;
            cur=cur->next;
        }
        return pre;
    }
};

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值