剑指offer--编程题参考代码(4)

为了将链表搞透,继续分享链表的题,将链表反转,合并两个链表,链表进行循环右移,还有数组的操作,由于篇幅,加上冒泡,最小堆的代码。(很抱歉散乱的上传代码,数组题,逻辑题,链表没清晰区分开)。基本上有的思路很多的 我写了几种实现。

20.反转链表

输入一个链表,反转链表后,输出链表的所有元素

这里改变了链表的结构

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
          if(pHead == NULL) return NULL;
          if(pHead->next==NULL) return pHead;
          ListNode* pri = pHead;   
          ListNode* cur = pHead->next;
          pri->next = NULL;
          ListNode* q = NULL;
        while(cur->next!=NULL)
            {
             q = cur;
             cur =cur->next;
             q->next = pri;
             pri=q;
        }
        cur->next=pri;       
        return cur;
    }
};

21.从尾到头打印链表

输入链表的表头,输出为需要打印的“新链表”的表头

(这里需要用 容器存储每个结点的数据)

1.用上面代码略微改动

修改链表结构:

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
          vector<int> list1;
          if(head == NULL){
             
            return list1;
              }
        if(head->next==NULL)
        {
             list1.push_back(head->val);
            return list1;
        }
          ListNode* pri = head;   
          ListNode* cur = head->next;
          pri->next = NULL;
          ListNode* q = NULL;
        while(cur->next!=NULL)
            {
             q = cur;
             cur =cur->next;
             q->next = pri;
             pri=q;
        }
        cur->next=pri;    
        while(cur)
            {
            list1.push_back(cur->val);
            cur =cur->next;
        }
        return list1;
    }
};
2.利用栈(出栈时候就是逆序,但栈对内存消耗很大。牛客上时间空间都做限制,通不过,但这是一种方法)

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
        vector<int> list1;
        if(head == NULL)       
            return list1;      
         stack<int> stack1;
        while(head)
            {
            stack1.push(head->val);
            head =head->next;
        }
        while(!stack1.empty()){
            list1.push_back(stack1.top());
        }
            
        return list1;
    }
};
3.不改变链表的结构:

只是逆序输出结点,不产生新表(递归):

//利用vector的函数
vector<int> printListFromTailToHead(struct ListNode* head) {
        vector<int> v;
        while(head != NULL)
        {
            v.insert(v.begin(),head->val);
            head = head->next;
        }
        return v;
    }
//基本的push_back压入
class Solution {
public:
    vector<int> list1;
    vector<int> printListFromTailToHead(struct ListNode* head) {
         if(head==NULL)
             return list1;
       
         list1=printListFromTailToHead(head->next);      
         list1.push_back(head->val);
         return list1;
    }
};

22.合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==NULL)
            return pHead2;
        if(pHead2==NULL)
            return pHead1;
        ListNode* pHead=NULL;  //保存新的头结点
        ListNode* p1=pHead1;   //为了写的方便,就将p1.p2替换原来的两个头结点
        ListNode* p2=pHead2;
        ListNode* pre=pHead1;
        ListNode* pT=NULL;
        if(p2->val<=p1->val){    //确定头结点
            pHead = p2;
            p2=p2->next;
            pHead->next=p1;
            pre = pHead;
                }
        else{
            pHead =p1;
            p1=p1->next;
            pre =pHead;
        }
              //将2插入1中
            while(p1!=NULL&&p2!=NULL){
                if(p2->val<p1->val){
                    pT=p2;
                    p2=p2->next;
                    pre->next=pT;
                    pT->next=p1;
                }
                else{
                    pre=p1;
                    p1=p1->next;
                }
                    
            }
            if(p1==NULL&&p2!=NULL){
            pre->next = p2;
            p2=p2->next;
             }
            if(p2==NULL&&p1!=NULL) {
                pre->next = p1;
                p1=p1->next;
                
            }
        return pHead;
    }
};

23.左旋转字符串

(即循环右移字符串)S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。

//思想:比如adcd。先adcdabcd。这样随便哪个位置取4位 cdab,这样的都可以

class Solution {
public:
    string LeftRotateString(string str, int n) {
       
       int len = str.length();
       if(len == 0) return "";
        n = n % len;
        str += str;             //直接两个相同的串连接,然后位移的位置取原长度的字符串
        return str.substr(n, len); 

    }
};
//利用string类的substr函数求子串,再连接也可以。(不过上面的方法让你很有新的思路)
class Solution {
public:
    string LeftRotateString(string str, int n) {
       
       int len = str.length();
       if(len == 0) return "";
       string str1=str.substr(n,len);
       string str2=str.substr(0,n);
       string str3 =str1+str2;
        return str3;

    }
};

24.旋转数组的最小数字(类似上面旋转字符串)

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

//思想:从第二个元素和第一个元素比,因为前面递增的,出现比第一个小的,就是旋转的起始
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()==0)
            return 0;
        unsigned long i=0;
       for(;i<rotateArray.size();i++){
            if(rotateArray[i]<rotateArray[0])
               return rotateArray[i];
           }
        return rotateArray[0];
    }
};

//思想:每个数和前面的比,突然比前面的小的, 就是旋转数组的起始数
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()==0)
            return 0;
        if(rotateArray.size()==1)
            return  rotateArray[0];
        unsigned long i=0;
       for(;i<rotateArray.size();i++)
            if(rotateArray[i]>rotateArray[i+1])
               return rotateArray[i+1];
        return rotateArray[0];
    }
};

25.最小的K个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。


最小堆:
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> result ;
        if(k > input.size()) return result;
        for(int i = 0; i < k ; i ++){
            heapSort(input,i,input.size());
            result.push_back(input[i]);
        }
        return result;
    }
};

冒泡(比较慢)取前k个数
class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> output;
        if(input.size()<=0||k<=0||k>input.size())
            return output;
        int num=input.size(), i,j,temp=0;
        for( i=0;i<num-1;i++)
           for( j=0;j<num-1-i;j++){
            if(input[j]>input[j+1]){
             temp=input[j];
            input[j]=input[j+1];
            input[j+1]=temp;
        }
        }
      for(int i=0;i<k;i++){
          output.push_back(input[i]);
      }
        return output;
    }
};







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值