笔试强训day28(猴子分桃,反转部分单向列表)

本文介绍了两个算法问题:猴子分桃和反转部分单向列表。在猴子分桃问题中,通过数学推理和递归公式,得出猴子分桃的最小剩余桃子数量。在反转部分单向列表问题中,利用双指针技巧实现指定区间的列表反转。两题均提供了C++代码实现。
摘要由CSDN通过智能技术生成

目录

第一题-猴子分桃

第二题-反转部分单向列表


第一题-猴子分桃

思路:

        假设有n个小猴子,总共有x个桃子,举例,现在n=3,

 由以上推理得,现在有n个猴子,则剩余桃子数量是((4/5)^n*x-(4/5)^n - (4/5)^(n-1)....-4/5)

我们先单独把s = -(4/5)^n - (4/5)^(n-1)....-4/5)拿出来,

用错位相减法,得到(4/5)*s = -(4/5)^(n+1) - (4/5)^(n)....-(4/5)(n+1))

得到(1/5)s = - 4/5 + (4/5)^n-1

在将剩余桃子数量得第一个((4/5)^n*x部分拿下来,

得到剩余桃子数量是4^n/5^n * (x+4) - 4,由于桃子剩余数量不可能是分数,又要最小值,

所以5^n = x + 4

所以x = 5^n - 4,为总共有多少个桃子

老猴子最少能得到得桃子数,等于小猴子数量加上最后剩余得桃子数量,

所以是4^n/5^n * (x+4) - 4+n,将x = 5^n - 4带入其中4^n/5^n * (5^n - 4+4) - 4+n,

化简为4^n - 4+n

#include<iostream>
#include<math.h>
using namespace std;
int main ()
{
    int n;//猴子数量
    while(cin>>n)
    {
        if(n == 0)
            break;
        else
        {
            long num = pow(5, n) - 4;
            long left = pow(4, n) - 4 + n;
            cout<<num<<" "<<left<<endl;;
        }
    }
    return 0;
}

第二题-反转部分单向列表

思路:

        只要看翻转部分就好,其他都是系统写好了的,为了方便我们定义一个哨兵位,首先找到需要反转的区间,然后利用三个指针将翻转区间翻转,然后首尾连接输出即可,注意翻转时细节,防止next指向空

# include <bits/stdc++.h>
using namespace std;

struct list_node{
    int val;
    struct list_node * next;
};

list_node * input_list(void)
{
    int n, val;
    list_node * phead = new list_node();
    list_node * cur_pnode = phead;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &val);
        if (i == 1) {
            cur_pnode->val = val;
            cur_pnode->next = NULL;
        }
        else {
            list_node * new_pnode = new list_node();
            new_pnode->val = val;
            new_pnode->next = NULL;
            cur_pnode->next = new_pnode;
            cur_pnode = new_pnode;
        }
    }
    return phead;
}


list_node * reverse_list(list_node * head, int L, int R)
{
    list_node* phead = new list_node;
    phead->next = head;
    list_node* right = head;
    list_node* left = head;
    while(--L)
    {
        right = right->next;
    }
    while(--R)
    {
        left = left->next;
    }
    list_node* cur = right;
    list_node* next = cur->next;
    list_node* pre = nullptr;
    
    while(pre != left)
    {
        cur->next = pre;
        pre = cur;
        cur = next;
        if(next)
            next = next->next;
    }
    right->next = cur;
    cur = phead;
    while(cur->next!=right)
    {
        cur = cur->next;
    }
    cur->next = left;
    return phead->next;
}

void print_list(list_node * head)
{
    while (head != NULL) {
        printf("%d ", head->val);
        head = head->next;
    }
    puts("");
}


int main ()
{
    int L, R;
    list_node * head = input_list();
    scanf("%d%d", &L, &R);
    list_node * new_head = reverse_list(head, L, R);
    print_list(new_head);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penguin_bark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值