剑指offer-第12题方法总结

<span style="font-family:SimSun;"></span><pre name="code" class="cpp">

题目:输入数字n,按顺序打印从1位到最大n位的十进制整数 。例如:输入3,则从1打印到999.

乍一看,这个问题很简单啊!!!

void
output(int
n)

{

int
i = 0;

for
(i = 1; i < pow(10,
n ); i++)

{

printf(
"%d\n", i);

}

}

如果写成上面这种形式,那就恭喜你掉到坑里了^v^。

这里的陷阱就是,整型是有范围的,如果你输入的位数超出了整型的范围,那么就不能输出正确的结果。为了解决这个越界问题,我们可以用数组来保存这个n位数的每一位,整型数组和字符数组都可以,下面使用整型数组。

分析:这里有两种解决办法,一种是模拟加法器,另一种是使用递归的方式将这个n位数的全排列输出。

第一种:

模拟加法器:因为n是在程序运行的时候才输入的,所以我们采用动态内存来开辟一个具有 n个元素的数组,用来保存,这n位。

首先我们将这个数组初始化为0,然后只给最低位进行自增,当最低位等于10时产生进位,这时再将最低位清零,这样依次循环往复,直到最高位变成10,这时就完成了打印。

这有两个需要注意的问题!!!

1、进位:除了最高位不用进位之外,其余位都有可能产生进位,所以在编写进位时应当要注意其适用性。

2、在打印时,假设大小为3的数组 里面保存的是098,则打印出来的就是098,这样不符合我们平常逻辑,所以我们要自己实现一个打印函数,让它从第一个不为0的数开始打印。

第二种:

递归:假设输入一个3,则这三位就从 001一直到999,组合下来是10的3次方减1种可能。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

//第一种

void print(int arr[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		if (arr[i] != 0)
			break;
	}
	for (; i < n; i++)
	{
		printf("%d", arr[i]);
	}
	printf("\n");
}
int counts(int *p, int n)
{
	int i = 0;
	int num = 0;                                      //设置一个进位信号
	for (i = n - 1; i >= 0; i--)
	{
		p[i]+=num;                                //如果num不为0则,给p[i]进位
		num = 0;                                  //进位完成后要将num置0
		if (i == n - 1)                           //给最低位自增
			p[i]++;
		if (p[i]>= 10)                            //如果p[i]等于10,则有可能要进位
		{
			if (i > 0)                         //如果不是最高位,则进位
			{
				p[i] -= 10;                //将p[i]清零
				num = 1;                   //将进位信号置
			}
			else
			{
				return 0;                  //如果是最高位,则程序结束
			}
		}
		else
		{
			break;                               //如果不进位,则跳出循环进行打印
		}
	}
	return 1;                                           //返回1进行打印
}

void output(int *p, int n)
{
	while (counts(p, n))
	{
		print(p, n);
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int *p = (int *)calloc(n, sizeof(int));
	output(p, n);
	free(p);
	p = NULL;
	system("pause");
	return 0;
}

//第二种
void print(int arr[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)                     //寻找到第一个不为0的数
	{
		if (arr[i] != 0)
			break;
	}
	for (; i < n; i++)                          //从这个数开始打印
	{
		printf("%d", arr[i]);
	}
	printf("\n");
}

void arrang(int *p, int n, int m)
{
	int i = 0;
	if (m == n - 1)
	{
		print(p, n);                    //递归终止条件
		return;
	}
	for (i = 0; i < 10; i++)
	{
		p[m + 1] = i;
		arrang(p, n, m + 1);            //对着n位数进行全排列,每一位都有0到9十种可能
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int *p = (int *)calloc(n, sizeof(int));
	arrang(p, n, -1);
	free(p);
	system("pause");
	return 0;
}

时间: 2024-10-18 15:01:41

剑指offer-第12题方法总结的相关文章

剑指offer第四题方法总结

题目:输入一个字符串,要求将这个字符串中所有空格的位置都替换成"%20".例:输入I love you. 输出I%20love%20you. 分析:空格是一个字符,%20是三个字符,所以替换的时候要向后挪动. 这里有三种方法. 第一种:从前向后遍历字符串,遇到一个空格,则将这个空格之后的字符'\0'开始依次向后挪动两个字符,然后再放入%20,直到遍历完整个字符串.这种方法效率比较低. 第二种:重新创建一个字符数组,将这个字符串拷贝过来,遇到空格就替换成%20. 这种方法虽然效率高,但是

剑指Offer系列之题11~题15

目录 11.矩形覆盖 12.二进制中1的个数 13. 数值的整数次方 14.调整数组顺序使奇数位于偶数前面 15.链表中倒数第k个结点 11.矩形覆盖 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 比如n=3时,2*3的矩形块有3种覆盖方法: 斐波那契数列的应用 第一次竖着放一块类比为走一步,第一次横着放两块类比为走两步 代码与上面的斐波那契数列类题目类似,此处不再赘述:剑指Offer系列之题6~题10. 12.

《剑指offer》刷题目录

<剑指offer>刷题目录 面试题03. 数组中重复的数字 面试题04. 二维数组中的查找 面试题05. 替换空格 面试题06. 从尾到头打印链表 面试题07. 重建二叉树 原文地址:https://www.cnblogs.com/qujingtongxiao/p/12652970.html

剑指offer 面试29题

面试29题: 题目:顺时针打印矩阵(同LeetCode 螺旋矩阵打印) 题:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10. 解题方法一:详见剑指offer 解题代码: # -*- coding:utf-8 -*- class Solution: # matrix类型为二维列表,需要返回

《剑指Offer》附加题_用两个队列实现一个栈_C++版

在<剑指Offer>中,在栈和队列习题中,作者留下来一道题目供读者自己实现,即"用两个队列实现一个栈". 在计算机数据结构中,栈的特点是后进先出,即最后被压入(push)栈的元素会第一个被弹出(pop);队列的特点是先进先出,即第一个进入队列的元素将会被第一个弹出来.虽然栈和队列特点是针锋相对,但是两者却相互联系,可以互相转换. 在"用两个队列实现一个栈"问题中,我们用两个队列的压入和弹出来模拟栈的压入和弹出.我们通过画图的手段把抽象的问题形象化. 在上

浅谈《剑指offer》原题:求1+2+……+n

<剑指offer>上的一道原题,求1+2+--+n,要求不能使用乘除法,for.while.if.else.switch.case等关键字以及条件判断语句(a?b:c). 第一次看到这道题大约有一年的时间了,在霸笔网易的时候,当时我就晕了...心想这是神马东西,后来发现这是原题!!然后后悔自己没看过书了... <剑指offer>上给出了不错的解法,但是这里有个解法更巧妙,虽然技术含量不高,但是可以参考,这就是<程序员面试笔试宝典>中所给出的答案. 解法一:利用宏定义求解

剑指offer 面试14题

面试14题: 题目:剪绳子 题:给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,且n>1,m>1),每段绳子的长度记为k[0],k[1],k[2],...,k[m].请问k[0]*k[1]*...*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积为18. 解题思路:基于动态规划和贪婪算法,详见剑指offer P96 解题代码: # -*- coding:utf-8 -*- class Solution: def Max

剑指offer 面试26题

面试26题: 题目:树的子结构 题:输入两棵二叉树A和B,判断B是不是A的子结构. 解题思路:递归,注意空指针的情况. 解题代码: # -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def HasSubtree(self, pRoot1, pRoot2): # write co

《剑指offer》算法题第三天

今日题目: 斐波那契数列 青蛙跳台阶问题(及其变种:变态跳台阶) 矩形覆盖 旋转数组的最小数字 矩阵中的路径 机器人的运动范围 细心的同学会发现,第1,2,3题其实对应的是<剑指>书上的同一道题目,即第10题斐波那契数列,这类问题属于递归问题,虽然思路比较简单,但却是属于那种不看答案想不出来,看了答案恍然大悟的题目,因此在平时同学们和博主都应该多练练这一类型的题目,培养这种递归的思维.有趣的是,博主在做题的时候发现这三道题目是可以用动态规划的思路来解决的,而且往往动态规划的所用的时间是要低于递

《剑指offer》算法题第十一天

今日题目: 滑动窗口的最大值 扑克牌中的顺子 圆圈中最后剩下的数字 求1+2+3+...+n 不用加减乘除做加法 构建乘积数组 今天的题目比较有意思,可以学到很多知识,包括第1题中的数据结构--双向队列,第3题约瑟夫环问题等. 1.滑动窗口的最大值 题目描述: 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}: 针对数组{2,3,4,2,6,