提示:以下是本篇文章正文内容,下面案例可供参考
一、约瑟夫环
个人认为有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);
}
之所以老是忽视特殊情况,还是因为本人练习不足,对树的理解不够深入。
总结
诸君共勉