首页 > 其他分享 >《剑指Offer》-46-把数字翻译成字符串

《剑指Offer》-46-把数字翻译成字符串

时间:2023-08-10 14:48:30浏览次数:46  
标签:10 num 数字 nums 46 Offer int 翻译成 25

读题

数字 0 ~ 25 分别对应了 a ~ z 一共 26 个字母

现在给一个数字,比如 12258,问可能对应多少种不同的翻译?

比如:1,2,2,5,8
12,2,5,8
12,25,8
1,22,5,8
1,2,25,8

一共 5 种

思路

使用动态规划的三要素:

  1. 数组元素定义
  2. 数组初始化
  3. 状态转移方程

1225 有几种可能的翻译?
1,2,2,5
1,22,5
1,2,25
12,2,5
12,25
也是 5 种,而且可以很明显地看出,这就是 12258 对应的 5 种排列,这是因为新增的 8 对整体种数没有影响,因为 58 并不能构成一种翻译,即前一个数的末尾数字和新数字并不能够构成可能性,出现在:前末位数字是 0 / 构成的新数字 > 25

那么 122 有几种可能的翻译?
1,2,2
12,2
1,22
一共三种,对于新增的 5,与末尾数字构成的 25 会影响种数:也就是 + 除去 25 后剩下 12 可能的种数

这突然让我想到了排列组合问题,只要剔除不符合要求的数字就可以了

那这么一分析,现在我有了两个思路,1 是组合(剔除不符合要求的),2 是动态规划

动态规划

第一次提交通过的代码

	int translateNum(int num) {
		// 将一个数字按位放入一个数组中
		vector<int> nums;
		while (num > 0) {
			nums.insert(nums.begin(),num % 10);
			num /= 10;
		}
		// reverse(nums.begin(), nums.end());
		int len = nums.size();
		vector<int> dp(len+1, 1);// 多一位,0位置不使用
		for (int i = 2; i <= len; i++) {
			// 判断新数字和原本的末尾数字相加 ?>25 && 末位数字!=0
			if (nums[i-2] != 0 && (nums[i - 2] * 10 + nums[i-1]) <= 25) {
				dp[i] = dp[i - 1] + dp[i - 2];
			}
			else dp[i] = dp[i - 1];
		}
		return dp[len];
	}

这里用insert()在头位置插入可以避免使用push_back()reverse()翻转数组

接下来我们尝试优化算法,将一维数组尝试用常数变量替代

	int translateNum(int num) {
		vector<int> nums;
		while (num > 0) {
			nums.insert(nums.begin(),num % 10);
			num /= 10;
		}
		int prepre =1, pre = 1;
		for (int i = 2; i <= nums.size(); i++) {
			if (nums[i - 2] != 0 && (nums[i - 2] * 10 + nums[i - 1]) <= 25) {
				pre = pre + prepre;
				prepre = pre - prepre;
			}
			else prepre = pre;
		}
		return pre;
	}

但是似乎并没有什么优化效果

更好的做法是,将两个循环统一并且不再使用额外的 nums 数组
这是一种逆推的做法

	int translateNum(int num) {
		int prepre = 1, pre = 1,lastDigit = num%10;
		num /= 10;

		while (num > 0) {
			int currentDigit = num % 10; // 获取当前位数字
			int combined = currentDigit * 10 + lastDigit;

			int temp = pre;
			if (combined >= 10 && combined <= 25) {
				pre += prepre;
			}
			prepre = temp;

			lastDigit = currentDigit;
			num /= 10;
		}
		return pre;
	}

ChatGPT 给出的最终优化后的代码,一开始我还很不能理解优化算法中的 prepre 和 pre,后来意识到其实从后往前推和从前往后推并没有区别,它们的种数是不会变化唯一确定的

标签:10,num,数字,nums,46,Offer,int,翻译成,25
From: https://www.cnblogs.com/yaocy/p/17619890.html

相关文章

  • 剑指 Offer 26. 树的子结构(中等)
    题目:classSolution{public://本方法运用两层递归,非常巧妙booltraversal(TreeNode*root1,TreeNode*root2){//判断当前两个节点的递归if(root2==nullptr)returntrue;......
  • 《剑指Offer》-61-扑克牌中的顺子
    判断是否为连续的数字,需要额外考虑的情况有一个,就是0可以代表任何数字,并且最多出现两次给出的长度为5的数组不一定是顺序 boolisStraight(vector<int>&nums){ sort(nums.begin(),nums.end()); //没有0的情况 if(nums[0]==0){ //只有一个0的情况 ......
  • 剑指 Offer 28. 对称的二叉树(简单)
    题目:classSolution{public:booltraversal(TreeNode*left,TreeNode*right){//递归判断左右两个**镜像**节点if(left==nullptr&&right!=nullptr)returnfalse;elseif(left!=nullptr&&right==nullptr)returnfalse;el......
  • CodeForces CF1846G 题解
    CodeForcesCF1846G题解CodeForces题目链接洛谷题目链接标准答案是状压之后,转化成Dijkstra算法跑最短路。我这里提供一个不一样的思路。题意简述主人公得了病,有部分类型的症状。所有类型症状共有\(n\)种,用长为\(n\)的01串表示是否有那种症状。共有\(m\)种药,吃......
  • 剑指 Offer 32 - III. 从上到下打印二叉树 III(中等)
    题目:解法一:classSolution{public:voidtraversal(TreeNode*cur,vector<vector<int>>&result,intdepth){if(cur==nullptr)return;if(result.size()==depth)result.push_back(vector<int>());result[depth].pu......
  • 剑指 Offer 32 - I. 从上到下打印二叉树(中等)
    题目://考察BFS(广度优先搜索)classSolution{public:vector<int>levelOrder(TreeNode*root){if(root==nullptr)return{};//一定不要漏了排除空树的情况vector<int>result;deque<TreeNode*>que;//用一个队列,利......
  • 代码随想录算法训练营第七天|力扣334.反转字符串、力扣541.反转字符串II、剑指offer05
    字符串反转字符串(力扣344.)如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。毕竟面试官一定不是考察你对库函数的熟悉程度,如果使用python和java的同学更需要注意这一点,因为python、java提供的库函数十分丰富。如果库函数仅仅是解题过程中的一小部分,并且......
  • 剑指 Offer 07. 重建二叉树
    classSolution{privateMap<Integer,Integer>indexMap;publicTreeNodemyBuildTree(int[]preorder,int[]inorder,intpreorder_left,intpreorder_right,intinorder_left,intinorder_right){if(preorder_left>preorder_right)......
  • 剑指 Offer 07. 重建二叉树
    输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 示例1:Input:preorder=[3,9,20,15,7],inorder=[9,3,15,20,7]Output:[3,9,20,null,null,15,7]示例2:Input:preorder=[-1],inorder=......
  • 剑指 Offer 07. 重建二叉树
    输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。示例1:Input:preorder=[3,9,20,15,7],inorder=[9,3,15,20,7]Output:[3,9,20,null,null,15,7]示例2:Input:preorder=[-1],inorder......