JAVA有哪十个算法,算法17(根据上排给出十个数,在其下排填出对应的十个数,要求下排每个数都是先前上排那十个数在下排出现的次数,java版本 )...

题目:

给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数

要求下排每个数都是先前上排那十个数在下排出现的次数。

上排的十个数如下:【0,1,2,3,4,5,6,7,8,9】

举个例子,

上排数值: 0,1,2,3,4,5,6,7,8,9

下排数值: 6,2,1,0,0,0,1,0,0,0

0在下排出现了6次,1在下排出现了2次,

2在下排出现了1次,3在下排出现了0次....

思路一:

这样的题目有点意思,但是仔细想想,它的原型跟八皇后有点类似,都是用回溯递归的方法去一次一次尝试,直到找出正确解。

具体的想法是:不断的去从下排数组中捉取在上排数组中对应位置中出现的个数,如果个数不对就更新下排数组中对应的值,只到找到正确值。(下排数组先初始为任意值)

如:

上排数组A:0,1,2,3,4,5,6,7,8,9

下排数组B:0,1,2,3,4,5,6,7,8,9

从上牌数组Index = 0开始,A[0] = 0,0在下排数组中的个数为1,那么下排数组B此时就要更新为:1,1,2,3,4,5,6,7,8,9,

Index = 1, A[1] = 1, 1在下排数组中的个数为2,那么下排数组B此时就要更新为:1,2,2,3,4,5,6,7,8,9,从此不断的往下进行,只要找不到正确值就一直往下进行,如果Index >= 数组长度时,那么重新恢复Index = 0再往下进行测试直到找出正确解。

代码如下:

/*====================================

Copyright by July  2010年10月18日

Modified by yuucyf.   2011.04.28

======================================*/

#define  MAX_LEN     10

class C_NumberTB

{

private:

int m_aryTop[MAX_LEN];

int m_aryBottom[MAX_LEN];

bool m_success;

public:

C_NumberTB();

public:

int* GetBottom();

void SetNextBottom();

int GetFrequecy(int nValue);

};

C_NumberTB::C_NumberTB()

{

m_success = false;

//format top

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

{

m_aryTop[i] = i;

m_aryBottom[i] = i;

}

}

int* C_NumberTB::GetBottom()

{

int i = 0;

while(!m_success)

{

i++;

SetNextBottom();

}

return m_aryBottom;

}

//set next bottom

void C_NumberTB::SetNextBottom()

{

bool bRet = true;

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

{

int nFreq = GetFrequecy(i);

if(m_aryBottom[i] != nFreq)

{

m_aryBottom[i] = nFreq;

bRet = false;

}

}

m_success = bRet;

}//get frequency in bottom

int C_NumberTB::GetFrequecy(int nValue) //此处的nValue 即指上排的数i

{

int nCnt = 0;

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

{

if(m_aryBottom[i] == nValue)

nCnt++;

}

return nCnt; //nCnt 即对应nFreq

}

int _tmain(int argc, _TCHAR* argv[])

{

C_NumberTB objTB;

int* pResult = objTB.GetBottom();

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

{

cout << *pResult++ << endl;

}

return 0;

}

/**

*

*/

package com.lhp;

import java.util.InputMismatchException;

import java.util.Scanner;

/**

第6 题

给你10 分钟时间,根据上排给出十个数,在其下排填出对应的十个数

要求下排每个数都是先前上排那十个数在下排出现的次数。

上排的十个数如下:

【0,1,2,3,4,5,6,7,8,9】

初看此题,貌似很难,10 分钟过去了,可能有的人,题目都还没看懂。

举一个例子,

数值: 0,1,2,3,4,5,6,7,8,9

分配: 6,2,1,0,0,0,1,0,0,0

0 在下排出现了6 次,1 在下排出现了2 次,

2 在下排出现了1 次,3 在下排出现了0 次....

以此类推..

*/

/**

* ...

*/

class BottomArrGenerate {

/**

* 按规则生成数组

* @param 数组长度

* @return 生成的数组

*/

public static int[] generateArr(int n) {

if (n < 4) {

System.out.println("请输入不小于4的整数");

return null;

}

int[] top = new int[n]; // 0-n一次排列的数字

int[] bottom = new int[n]; // 结果

for (int i = 0 ; i < top.length; i++)

top[i] = i;

for (int m = 0; m < n + 2; m++) {

boolean flag = true; // 找到结果标志

for (int i = 0; i < n; i++) { // 逐位对应

int count = getCount(i, bottom);

if (bottom[i] != count) { // 和上一次算出来的次数不符

bottom[i] = count;

flag = false;

}

}

if (flag) // 连续2次得到的次数一样,则为正确结果

break;

if (n + 1 == m && !flag) { // 算法有缺陷,n=5时是有结果2,1,2,0,0的,底下结果如果有2个数字等于上面的数字就算不出来

System.out.println("找不到结果");

return null;

}

}

return bottom;

}

/**

* 获得某数在数组中出现的次数

* @param 数

* @param 数组

* @return 数字在数组中出现次数

*/

public static int getCount(int num, int[] arr) {

int count = 0;

for (int i = 0; i < arr.length; i++) {

if (num == arr[i]) {

count++;

}

}

return count;

}

}

public class Six {

public static void main(String[] args) {

Scanner scan = new Scanner(System.in);

int[] a = null;

try {

a = BottomArrGenerate.generateArr(scan.nextInt());

} catch (InputMismatchException e) {

System.out.println("请输入整数");

}

if (a != null) {

for (int i = 0; i < a.length; i++) {

System.out.print(i + "\t");

}

System.out.println();

for (int i : a) {

System.out.print(i + "\t");

}

}

}

}

给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数

要求下排每个数都是先前上排那十个数在下排出现的次数。

上排的十个数如下:

【0,1,2,3,4,5,6,7,8,9】

举一个例子,

数值: 0,1,2,3,4,5,6,7,8,9

分配: 6,2,1,0,0,0,1,0,0,0

0在下排出现了6次,1在下排出现了2次,

2在下排出现了1次,3在下排出现了0次....

以此类推..

解题思路:关键是理解“要求下排每个数都是先前上排那十个数在下排出现的次数”。

做以下分析:设总共有n个数,上排a[0...n-1],下排b[0...n-1],。

1)下排n个数的累加和为n,即b[0]+b[1]+...+b[n-1] = n

2)ai*bi的累加和也为n,即a[0]*b[0]+a[1]*b[1]+...+a[n-1]*b[n-1] = n

3)对于b中任意一个元素b[j], 都存在i,a[i] = b[j].

4)对于b中任意一个元素b[j],都有b[j] >= 0

5)如果a中存在负数。其在b中出现的次数一定为0. 如果a中数值大于n,则其出现次数也为0.

6)a中至少有两个非0数值在b中出现的次数非0

a:由1)n > n*b[i],其中b[i]为最小值,则a b中一定均有数值0,否则无解。设a[0] = 0,b[0]为a[0]在b中出现次数。

b:由于b中一定存在0,则0的出现次数一定大于0,因此b[0]>0 且b[0] < n,b[1...n-1]中至少一个值为0. 非0元素出现的次数一共是n-b[0].

c:有2)和6)对任意a[i],a[i]*b[i] < n,即b[i] < n/a[i],对所有a[i]>=n/2的元素中,在b中出现的次数必须最多只有1个出现次数不为0,且为1.其余出现次数均为0,即[1, n/2)范围内最多只有n/2-1个元素,故0出现的次数必不小于n/2, [n/2,n)范围内的元素必有一个出现次数为1。因此a数列中也必须有1,否则无解。

d:有c得在数值范围为(0,n/2)中(假设有x这样的数)出现的次数和s为n - b[0]或n-b[0]-1。其中1出现的次数至少为1(由c得)。又如果1出现的次数为1,则1出现的次数已经为2,故1出现的次数必大于1.设为x,则x出现的次数至少为1,而x>1,如果x出现的次数大于1,那么必须要有其他数出现的次数为x,这样无法收敛。故x出现的次数只能为1,1出现的次数只能为2.

结论:

0出现的次数为n-4,1出现的次数为2.2出现的次数为1。n-4出现的次数为1.如果数列中无则四个数,无解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值