剑指offer真题11-15

本文探讨了链表与数组的多种高级操作,包括寻找链表中倒数第k个节点、反转链表、调整数组中奇偶数的位置,以及计算整数二进制表示中1的个数和求幂运算。通过具体实例,深入解析了这些算法的实现思路和代码细节。

11题:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示

//法一
//让n减去1,我们发现,在让他和原来的n按位与之后,n中的1会减少一个,依次循环下去,就可以累计出1的个数,且这个方式不用担心负数的问题
class Solution {
public:
     int  NumberOf1(int n) {
         int count = 0;
         while(n)
         {
             ++count;
             n = n & (n-1);
         }
         return count;
     }
};
//法二
//定义一个flag为1,左移一位就变成0010,循环下来,和n中的1依次按位与,再用计数器加起来即可
class Solution {
public:
     int  NumberOf1(int n) {
         int flag = 1;
         int count = 0;
         while(flag != 0)
         {
             if((n & flag) != 0)
         count++;
             flag = flag << 1;
         }
         return count;
     }
};

第12题:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方

class Solution {
public:
    double Power(double base, int exponent) {
    double res = 1, pre = base;
        int cur;
        if(exponent > 0)
            cur = exponent;
        else if(exponent == 0)
            return 1;
        else
		{
            if(base == 0)
                return 0;
            cur = -exponent;
		}
        while(cur != 0)
        {
            if((cur & 1) == 1)
                res *= pre;
                pre *= pre;
                cur >>= 1;
        }
        return (exponent >= 0 ? res : (1/res));
    }
};

第13题:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

//法一:
class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int> array_tmp;
        vector<int>::iterator a1, b1;
        a1 = array.begin();
        for(; a1 != array.end();)
        {
            if(*a1 % 2 == 0)
            {
                array_tmp.push_back(*a1);
                a1 = array.erase(a1);
            }
            else
                ++a1;
        }
        vector<int>::iterator a2, b2;
        a2 = array_tmp.begin();
        b2 = array_tmp.end();
        for(; a2 != b2; ++a2)
        {
            array.push_back(*a2);
        }
    }
};
//法二:冒泡排序
class Solution {
public:
    void reOrderArray(vector<int> &array) {
        for(int i = 0; i < array.size(); ++i)
        {
            for(int j = array.size()-1; j > i; --j)
            if(array[j] % 2 == 1 && array[j - 1] % 2 == 0)
            {
                swap(array[j], array[j - 1]);
            }
        }
    }
};

第14题:输入一个链表,输出该链表中倒数第k个结点

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead == nullptr || k == 0)
            return nullptr;
        ListNode* fast = pListHead, *slow = pListHead;
        while(k > 1)//特别注意,因为当k=1时,就不需要fast继续往后走了,如果fast此时继续往后走,slow就只能找到fast之前那个位置
        {
            if(fast->next != nullptr)
            {
                fast = fast->next;
            }
            else
                return nullptr;
            k--;
        }
        while(fast->next != nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

第15题:输入一个链表,反转链表后,输出新链表的表头。

//循环
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == nullptr)
            return nullptr;
        ListNode* pNode = pHead;
        ListNode* pReverseHead = nullptr;
        ListNode* pPrev = nullptr;
        while(pNode != nullptr)
        {
            ListNode* pNext = pNode->next;
            if(pNext == nullptr)
            {
                pReverseHead = pNode;
            }
            pNode->next = pPrev;
            pPrev = pNode;
            pNode = pNext;
        }
        return pReverseHead;
    }
};
//递归
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == nullptr || pHead->next == nullptr)
            return pHead;
        ListNode* pReverseList = ReverseList(pHead->next);
        pHead->next->next = pHead;//难点在这里,在这里实现两个节点的位置互换,head节点直接指向了他之后第二个节点,
									//跳过他之后的第一个节点,相当于换位置,再将head的next置为空就相当于,head再次变成了头节点
        pHead->next = nullptr;
        return pReverseList;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值