反转单链表+求单链表倒数第k个节点+不用加减乘除做加法

本文介绍了如何反转单链表以及在只遍历一次链表的情况下找到倒数第k个节点的方法,利用快慢指针解决。此外,还探讨了一个有趣的编程挑战:不用四则运算符实现整数相加,通过位运算来实现。
摘要由CSDN通过智能技术生成

一,逆置/反转单链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

1)反转指针
ListNode* ReverseList(ListNode* head)
{
    ListNode* cur == NULL;
    ListNode* prev == NULL;
    ListNode* next == NULL;
    if(head == NULL || haed->_next == NULL)//考虑没有节点或者只有一个节点的情况
    {
        return;
    }
    cur = haed;
    while(cur != NULL)
    {
        next = cur->_next;
        cur->_next =  prev;//指针反转
        prev = cur;
        cur = next;
    }
    if(cur == NULL)
    {
        head = prev;
        return head;
    }
}

这里写图片描述

2)借用栈实现
void Reverse(Node *&haed)
{
    if(head == NULL || head->_next == NULL)
    {
        return;
    }
    stack<Node*> s;

    Node* cur = head;//入栈
    while(cur->_next)
    {
        s.push(cur);
        cur = cur->_next;
    }
    head = cur;
    while(!s.empty())
    {
        Node* tmp = s.top();
        cur->_next = tmp;
        cur = tmp;
        s.pop();
    }
    cur->_next = NULL;
}

这里写图片描述
二,查找单链表倒数第k个节点 (要求只能遍历一次链表)
输入一个链表,输出该链表中倒数第k个节点。
思考过程:
(1)看到这个题目很自然会想到先走到链表的尾部,再从尾部回溯k步,但是本题中的链表是单向链表,只有从前往后的指针而没有从后向前的指针,所以回溯法行不通。
(2)假设一共有n个节点,那么倒数第k个节点就是从头结点开始的第n-k+1个节点,但是n未知,所以需要我们先遍历一遍链表统计出总结点的个数n,第二次走n-k+1步就能找到倒数第k个节点,但此方法又不符合只能遍历一次的题目要求。
(3)既然不能遍历两次,我们可以换一种思路,定义快慢两个指针,快指针从链表的头指针开始向后走k-1步,慢指针保持不动;从第k步起,慢指针也开始从头指针与快指针同步走,当快指针到达链表的尾节点时,慢指针正好指向倒数第k个节点。
为了更加明了第三种思路,我来画图举例来示范一次。

这里写图片描述
主代码:

ListNode* Findktail(ListNode* Head,size_t k)
{
    if(Head == NULL || k == 0)//排除异常情况
    {
        return NULL;
    }
    ListNode* fast == Head;//建立快慢指针
    ListNode* slow == Head;
    while(fast && --k)
    {
        fast = fast->_next;
    }
    if(fast == NULL)
    {
        return NULL;
    }
    if(k == 0)//当快指针走了k步
    {
        while(fast->_next != NULL)
        {
            fast = fast->_next;//慢指针从头跟着快指针同步走
            slow = slow->_next;
        }
    }
    return slow;
}

三,实现一个Add函数,让两个整数相加,但是不能使用+,-,*,/四则运算符
思路:求两数之和却不能使用四则运算,通过分析十进制数的相加机制我们可以联想到二进制数的位运算。
举个例子,5的二进制数101,17的二进制数为10001,我们试着把计算过程分为三步,第一步相加不进位。0+0为0,0+1与1+0均为1,因为不考虑进位所以在这里1+1也为0,可以观察到这个过程相当于异或运算。 第二步求得进位。对0+0,0+1,1+0而言都不会产生进位,只有1+1时,才会向前产生一个进位。此时可以认为两个数先做位与运算,然后再向左移动一位。 第三步把前两个步骤所得结果相加。

计算过程:
这里写图片描述

迭代法
int add(int num1,int num2)
{
    while(num2 != 0)
    {
        int tmp1 = (num1^num2);
        int tmp2 = (num1&num2)<<1;
        num1 = tmp1;
        num2 = tmp2;
    }
    return num1;
}
//递归
int add(int a,int b)
{
    if(b == 0)
        return a;
    else
    {
        int sum = a^b;
        int tmp = (a&b)<<1;
        add(sum,tmp);
    }
}
int main()
{
    printf("%d\n",add(10,5));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值