约瑟夫环与左子叶和问题


提示:以下是本篇文章正文内容,下面案例可供参考

一、约瑟夫环

在这里插入图片描述
个人认为有2种简单易想的方法:

1.环形链表
将n个人都存入链表,然后每次都在链表中删除一个人,直至环形链表仅剩1人。此法主要是C种没有对应库函数,需要写一堆。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType num;	
	struct SListNode* next;
}SLTNode;
SLTNode* BuySLTNode(int i);
void SListPushFront(SLTNode** pphead,int i);
SLTNode* fun(SLTNode* phead,int m,int n);
int main()	
{		int n;
	scanf("%d",&n); 
	SLTNode *L=NULL;
	int x;
	int i=n;
	while(i)
	{
		SListPushFront(&L,i);
		i--;
	}
		SLTNode *cur=L;
		while(cur->next)
		cur=cur->next;
		cur->next=L;
	int m;
	 	scanf("%d",&m);
	while(n)
	{
		L=fun(L,m,n);
		n--;
	}
	
	return 0;
}
SLTNode* BuySLTNode(int i)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->num=i;
	newnode->next = NULL;
	return newnode;
}
void SListPushFront(SLTNode** pphead,int i)
{
	SLTNode* newnode = BuySLTNode(i);
	newnode->next = *pphead;
	*pphead = newnode;
}
SLTNode* fun(SLTNode* phead,int m,int n)
{
	SLTNode* cur=phead;
	if(cur->next!=cur)
	{int a=m%n;
	a=(a+n-2)%n;
	while(a--)
	cur=cur->next;
	cur->next=cur->next->next;}
	else
	printf("%d ",cur->num);	
	return cur->next;
}

2.数组法
有N个人,我则开一个大小为N的数组,全部赋1,然后每删一人,就赋其0
经过N-1次循环,则数组中只有一人为1,再找到那人即可

#include<stdio.h>
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
/*本人犯了一个严重错误:
while(m>n)
m=m-n;
在只需走所有人一遍时,这样没问题,而需要走多遍时,它每次就会出错
因为随着人数减少,n<m时,每少一人都会差一次++
而自己愚蠢的一直没发现,唉
*/
    if (n == 1) {
        printf("1");
    } else {
        int i, s, c = 0;
        int num[n];
        for (i = 0; i < n; i++)
            num[i] = 1;
        for (int j = 0; j < n - 1; j++) {
            s = m;
            while (s) {
                if (c == n)
                    c -= n;
                if (num[c] == 1) {
                    if (s == 1)
                        num[c] = 0;
                    else
                        c++;
                    s--;
                } 
                else
                    c++;
            }
        }
        while (1) {
            if (c > n)
                c -= n;
            if (num[c] == 1) {
                printf("%d", c + 1);
                break;
            }
            c++;
        }

    }
    return 0;
}

二、左叶子之和

在这里插入图片描述
错误代码:
最开始想着写一个f用来求左子叶,然后树的左子叶之后就等于自己的左子叶加上右子树的左子叶
但是当树变大时,左子树不一定只有一个左子叶节点
而F也有许多问题,自己考虑不清

int f(struct TreeNode* root)
{
if(root->left!=NULL)
return f(root->left);
else if(root->left==NULL&&root->right==NULL)
return root->val;
return 0;
}
int sumOfLeftLeaves(struct TreeNode* root ) {
if(root==NULL)
return 0;
if(root->left==NULL)
return 0;
if(root->right==NULL)
return f(root)+sumOfLeftLeaves(root->left->right);
return f(root)+sumOfLeftLeaves(root->right)+sumOfLeftLeaves(root->left->right)+sumOfLeftLeaves(root->right->right);
}

这道题首先要解决的问题是如何划分子问题,

自己一开始划分为:自己的左子叶节点+自己右子树的左子叶节点
细细斟酌后,应该划分为:自己左树的左子叶节点之和+自己右树的左子叶节点之和

第二个问题是如何判断左子叶:
自己一开始想法是

if(root->left!=NULL&&root->left->left==NULL
&&root->left->right==NULL)
return root->left->val;

但这样的话
在这里插入图片描述
对于这种情况则会直接返回7,而忽视右树还可能有左子叶节点的情况

所以应该改为返回自己左子叶节点+右子树左子叶节点之和

if(root->left!=NULL&&root->left->left==NULL
&&root->left->right==NULL)
return root->left->val+sumOfLeftLeaves(root->right); 

最后代码如下:

int sumOfLeftLeaves(struct TreeNode* root ) {
    if(root==NULL)
    return 0;
    if(root->left!=NULL)
    if(root->left->left==NULL&&root->left->right==NULL)
    return root->left->val+sumOfLeftLeaves(root->right);  
    return sumOfLeftLeaves(root->left)+
    sumOfLeftLeaves(root->right);
    }

之所以老是忽视特殊情况,还是因为本人练习不足,对树的理解不够深入。


总结

诸君共勉

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值