C#,电话数字键盘问题(Mobile Numeric Keypad problem)的算法与源代码

1 电话数字键盘问题

提供移动数字键盘。您只能按向上、向左、向右或向下至当前按钮的按钮。不允许您按最下面一行的角点按钮(即.*和#)。

移动键盘

给定一个数N,找出给定长度的可能数。

示例:

对于N=1,可能的数字数为10(0、1、2、3、...、9)

对于N=2,可能的数字数为36

可能的数字:00、08、11、12、14、22、21、23、25等等。

如果我们从0开始,有效数字将是00、08(计数:2)

如果我们从1开始,有效数字将是11、12、14(计数:3)

如果我们从2开始,有效数字将是22、21、23、25(计数:4)

如果我们从3开始,有效数字将是33、32、36(计数:3)

如果我们从4开始,有效数字将是44,41,45,47(计数:4)

如果我们从5开始,有效数字将是55,54,52,56,58(计数:5)

....................................

....................................

我们需要打印可能的数字。

推荐做法

移动数字键盘

试试看!

N=1是普通情况,可能的数字数为10(0,1,2,3,...,9)

对于N>1,我们需要从某个按钮开始,然后移动到四个方向(向上、向左、向右或向下)中的任何一个,该方向指向有效的按钮(不应转到*、#)。继续这样做,直到获得N个长度编号(深度优先遍历)。

递归解决方案:

移动键盘是4X3的矩形网格(4行3列)

假设Count(i,j,N)表示从位置(i,j)开始的N个长度数字的计数

如果N=1 ,计数(i,j,N)=10

其他的 Count(i,j,N)=所有Count(r,c,N-1)之和,其中(r,c)是新的

长度1从当前有效移动后的位置

位置(i,j)

下面是上述公式的三种实现代码。

2 源代码

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
	public static partial class Algorithm_Gallery
	{
        #region 算法1
		private static int MNKP_Solve_Utility(char[,] keypad, int i, int j, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 1;
			}

			int[] row = { 0, 0, -1, 0, 1 };
			int[] col  = { 0, -1, 0, 1, 0 };

			int totalCount = 0;
			for (int move = 0; move < 5; move++)
			{
				int ro = i + row[move];
				int co = j + col[move];
				if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')
				{
					totalCount += MNKP_Solve_Utility(keypad, ro, co, n - 1);
				}
			}
			return totalCount;
		}

		public static int MNKP_Solve(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}

			int totalCount = 0;
			for (int i = 0; i < 4; i++) 
			{
				for (int j = 0; j < 3; j++) 
				{
					if (keypad[i, j] != '*' && keypad[i, j] != '#')
					{
						totalCount += MNKP_Solve_Utility(keypad, i, j, n);
					}
				}
			}
			return totalCount;
		}
		#endregion

		#region 算法2
		public static int MNKP_Solve_2th(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}
			int[] row = { 0, 0, -1, 0, 1 };
			int[] col = { 0, -1, 0, 1, 0 };

			int[,] count = new int[10, n + 1];

			for (int i = 0; i < 10; i++)
			{
				count[i, 0] = 0;
				count[i, 1] = 1;
			}

			for (int k = 2; k <= n; k++)
			{
				for (int i = 0; i < 4; i++) 
				{
					for (int j = 0; j < 3; j++) 
					{
						if (keypad[i, j] != '*' && keypad[i, j] != '#')
						{
							int num = keypad[i, j] - '0';
							count[num, k] = 0;

							for (int move = 0; move < 5; move++)
							{
								int ro = i + row[move];
								int co = j + col[move];
								if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')
								{
									int nextNum = keypad[ro, co] - '0';
									count[num, k] += count[nextNum, k - 1];
								}
							}
						}
					}
				}
			}

			int totalCount = 0;
			for (int i = 0; i < 10; i++)
			{
				totalCount += count[i, n];
			}
			return totalCount;
		}
		#endregion

		#region 算法3
		public static int MNTP_Solve_3th(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}
			int[] odd = new int[10];
			int[] even = new int[10];

			int useOdd = 0;
			for (int i = 0; i < 10; i++)
			{
				odd[i] = 1;
			}

			for (int j = 2; j <= n; j++)
			{
				useOdd = 1 - useOdd;

				if (useOdd == 1)
				{
					even[0] = odd[0] + odd[8];
					even[1] = odd[1] + odd[2] + odd[4];
					even[2] = odd[2] + odd[1] + odd[3] + odd[5];
					even[3] = odd[3] + odd[2] + odd[6];
					even[4] = odd[4] + odd[1] + odd[5] + odd[7];
					even[5] = odd[5] + odd[2] + odd[4] + odd[8] + odd[6];
					even[6] = odd[6] + odd[3] + odd[5] + odd[9];
					even[7] = odd[7] + odd[4] + odd[8];
					even[8] = odd[8] + odd[0] + odd[5] + odd[7] + odd[9];
					even[9] = odd[9] + odd[6] + odd[8];
				}
				else
				{
					odd[0] = even[0] + even[8];
					odd[1] = even[1] + even[2] + even[4];
					odd[2] = even[2] + even[1] + even[3] + even[5];
					odd[3] = even[3] + even[2] + even[6];
					odd[4] = even[4] + even[1] + even[5] + even[7];
					odd[5] = even[5] + even[2] + even[4] + even[8] + even[6];
					odd[6] = even[6] + even[3] + even[5] + even[9];
					odd[7] = even[7] + even[4] + even[8];
					odd[8] = even[8] + even[0] + even[5] + even[7] + even[9];
					odd[9] = even[9] + even[6] + even[8];
				}
			}

			int totalCount = 0;
			for (int i = 0; i < 10; i++)
			{
				totalCount += (useOdd == 1) ? even[i] : odd[i];
			}
			return totalCount;
		}
        #endregion
    }
}

3 源程序

using System;

using System.Collections;

using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm

{

public static partial class Algorithm_Gallery

{

#region 算法1

private static int MNKP_Solve_Utility(char[,] keypad, int i, int j, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 1;

}

int[] row = { 0, 0, -1, 0, 1 };

int[] col = { 0, -1, 0, 1, 0 };

int totalCount = 0;

for (int move = 0; move < 5; move++)

{

int ro = i + row[move];

int co = j + col[move];

if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')

{

totalCount += MNKP_Solve_Utility(keypad, ro, co, n - 1);

}

}

return totalCount;

}

public static int MNKP_Solve(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int totalCount = 0;

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 3; j++)

{

if (keypad[i, j] != '*' && keypad[i, j] != '#')

{

totalCount += MNKP_Solve_Utility(keypad, i, j, n);

}

}

}

return totalCount;

}

#endregion

#region 算法2

public static int MNKP_Solve_2th(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int[] row = { 0, 0, -1, 0, 1 };

int[] col = { 0, -1, 0, 1, 0 };

int[,] count = new int[10, n + 1];

for (int i = 0; i < 10; i++)

{

count[i, 0] = 0;

count[i, 1] = 1;

}

for (int k = 2; k <= n; k++)

{

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 3; j++)

{

if (keypad[i, j] != '*' && keypad[i, j] != '#')

{

int num = keypad[i, j] - '0';

count[num, k] = 0;

for (int move = 0; move < 5; move++)

{

int ro = i + row[move];

int co = j + col[move];

if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')

{

int nextNum = keypad[ro, co] - '0';

count[num, k] += count[nextNum, k - 1];

}

}

}

}

}

}

int totalCount = 0;

for (int i = 0; i < 10; i++)

{

totalCount += count[i, n];

}

return totalCount;

}

#endregion

#region 算法3

public static int MNTP_Solve_3th(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int[] odd = new int[10];

int[] even = new int[10];

int useOdd = 0;

for (int i = 0; i < 10; i++)

{

odd[i] = 1;

}

for (int j = 2; j <= n; j++)

{

useOdd = 1 - useOdd;

if (useOdd == 1)

{

even[0] = odd[0] + odd[8];

even[1] = odd[1] + odd[2] + odd[4];

even[2] = odd[2] + odd[1] + odd[3] + odd[5];

even[3] = odd[3] + odd[2] + odd[6];

even[4] = odd[4] + odd[1] + odd[5] + odd[7];

even[5] = odd[5] + odd[2] + odd[4] + odd[8] + odd[6];

even[6] = odd[6] + odd[3] + odd[5] + odd[9];

even[7] = odd[7] + odd[4] + odd[8];

even[8] = odd[8] + odd[0] + odd[5] + odd[7] + odd[9];

even[9] = odd[9] + odd[6] + odd[8];

}

else

{

odd[0] = even[0] + even[8];

odd[1] = even[1] + even[2] + even[4];

odd[2] = even[2] + even[1] + even[3] + even[5];

odd[3] = even[3] + even[2] + even[6];

odd[4] = even[4] + even[1] + even[5] + even[7];

odd[5] = even[5] + even[2] + even[4] + even[8] + even[6];

odd[6] = even[6] + even[3] + even[5] + even[9];

odd[7] = even[7] + even[4] + even[8];

odd[8] = even[8] + even[0] + even[5] + even[7] + even[9];

odd[9] = even[9] + even[6] + even[8];

}

}

int totalCount = 0;

for (int i = 0; i < 10; i++)

{

totalCount += (useOdd == 1) ? even[i] : odd[i];

}

return totalCount;

}

#endregion

}

}

相关推荐
盛夏绽放11 分钟前
Python字符串常用方法详解
开发语言·python·c#
好吃的肘子1 小时前
Elasticsearch架构原理
开发语言·算法·elasticsearch·架构·jenkins
nlog3n2 小时前
Go语言交替打印问题及多种实现方法
开发语言·算法·golang
kaixin_learn_qt_ing2 小时前
Golang
开发语言·后端·golang
ddd...e_bug2 小时前
Shell和Bash介绍
开发语言·bash
C4程序员3 小时前
Java百度身份证识别接口实现【配置即用】
java·开发语言
unityのkiven3 小时前
C++中的虚表和虚表指针的原理和示例
开发语言·c++
炒空心菜菜3 小时前
MapReduce 实现 WordCount
java·开发语言·ide·后端·spark·eclipse·mapreduce
(・Д・)ノ3 小时前
python打卡day27
开发语言·python
芯眼3 小时前
STM32启动文件详解(重点)
java·开发语言·c++·stm32·单片机·mybatis