今年腾讯的笔试题,求大佬解答。

chenguixuchen1 2019-04-07 03:09:14
输入是两个正整数n和k,把从1到2n这2n个数平均分成两份(每份n个数),每份分别排序,排序完成后的数组假设叫a和b,要求abs(ai-bi)>=k, (相同位置的数差的绝对值不少于k),输出有多少种分法。 当时没想出算法。。。另外这种和组合方式有关的问题感觉都不太会做,有大佬指点该去哪找针对性的练习么。。。
...全文
3480 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_39936465 2019-04-11
  • 打赏
  • 举报
回复
引用 31 楼 WMERP 的回复:
n=10 k=3 时有2927种分法,如果两个数组分前后的话再*2
不可能这么多的,请看清题目,分组后的数列是排序的。如果是无序求排列方法我觉得这样的题目是没有意义的,因为哪怕同样一组数用无序排法可以排出很多种组合,n越大这种组合越多。
lx_qq1290708840 2019-04-11
  • 打赏
  • 举报
回复
测试可用,欢迎前辈指正 import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; public class Test4 { static int total = 0; public static void main(String[] args) { System.out.print("请输入n:"); Scanner s1 = new Scanner(System.in); int n = s1.nextInt(); System.out.print("请输入k:"); Scanner s2 = new Scanner(System.in); int k = s2.nextInt(); fenpei(n, k); } public static void fenpei(int n, int k) { if (k > n) { System.out.println("无分配方案"); return; } List<Integer> list1 = new ArrayList<Integer>(); List<Integer> list2 = new ArrayList<Integer>(); // 初始化两个数组,临界条件为按顺序排列 for (int i = 1; i < 2 * n + 1; i++) { if (i <= n) { list1.add(i); } else { list2.add(i); } } Map map = new HashMap<>(); map.put("list1", list1); map.put("list2", list2); print(map, n, k); for (int i = 2; i <= n; i++) { for (int j = n + 1; j <= 2 * n; j++) { Map<String, List<Integer>> exchange = exchange(list1, list2, i - 1, j - n - 1); if (ckeck(exchange, k)) { print(exchange, n, k); } } } } private static void print(Map<String, List<Integer>> map, int n, int k) { total += 1; List<Integer> list1 = map.get("list1"); List<Integer> list2 = map.get("list2"); StringBuffer buffer1 = new StringBuffer(); StringBuffer buffer2 = new StringBuffer(); for (int i = 0; i < list1.size(); i++) { int list1value = list1.get(i); int list2value = list2.get(i); buffer1.append(list1value).append("\t"); buffer2.append(list2value).append("\t"); } System.out.println("n: " + n + "\tk: " + k + "\t第" + total + "种方案"); System.out.println(buffer1.toString()); System.out.println(buffer2.toString()); } private static boolean ckeck(Map<String, List<Integer>> map, int k) { List<Integer> list1 = map.get("list1"); List<Integer> list2 = map.get("list2"); boolean flat = true; for (int i = 0; i < list1.size(); i++) { int list1value = list1.get(i); int list2value = list2.get(i); int abs = Math.abs(list1value - list2value); if (k > abs) { flat = false; break; } } return flat; } private static Map<String, List<Integer>> exchange(List<Integer> list6, List<Integer> list7, int i, int j) { List<Integer> list1 = new ArrayList<>(list6); List<Integer> list2 = new ArrayList<>(list7); Integer ivalue = list1.get(i); Integer jvalue = list2.get(j); list1.remove(i); list2.remove(j); int num = 0; num = ivalue; ivalue = jvalue; jvalue = num; list1.add(ivalue); list2.add(0, jvalue); Map<String, List<Integer>> map = new HashMap<>(); map.put("list1", list1); map.put("list2", list2); return map; } public static List<Integer> paixu(List<Integer> list) { Collections.sort(list); return list; } }
上进Shang J 2019-04-11
  • 打赏
  • 举报
回复
刚学java懵逼中,摩拜大佬。
_明月 2019-04-11
  • 打赏
  • 举报
回复
引用 42 楼 WMERP 的回复:
[quote=引用 35 楼 _明月 的回复:]


楼主,能够讲讲你面试的是什么岗位么?


我做Java的,快2年了,做算法,感觉还是一窍不通,虽然当初大学时学过算法设计这门课。



算法这东西其实不关编程语言的事情,是和数学和统计学有关的,就像本题一样,你懂得数学和组合再会建模分析的话,用任何语言都是一样的,可以专门找些与算法有关的书籍和试题,多做多看熟练逻辑思维,等熟练后不管什么项目一看的时候头脑中马上就可以建立模型和逻辑关系就好了。[/quote]


好的,谢谢。我高中数学,大学数学学得还行。




wdonghai 2019-04-11
  • 打赏
  • 举报
回复
之前的算法是弄成了整个数组有序,而题目里面只是要求数组a和b有序,没要求整个数组有序。

package jp190410;

public class MyClass
{
static int n = 4;
static int k=2;
static int gCount=0;
static int[] b=new int[100];
static int[] a=new int[100];

public static void dfs(int step)
{
//if(gCount>=500) return;
if (step>n*2)
{
for (int i = 1; i <=n; i++)
{
if(Math.abs(a[i]-a[i+n])<k) return;
}

for(int i=2;i<=n;i++) //检查数组a和b是否有序,默认是升序
{
if (a[i]<a[i-1] ) return;
if (a[i+n]<a[i+n-1]) return;
}

gCount++;

StringBuffer s1=new StringBuffer();
s1.append("答案 "+String.format("%-4d",gCount)+" 数组a:[");
for(int i=1;i<=n;i++)
s1.append(String.format("%-4d", a[i]));
s1.append("] 数组b:[");
for(int i=n+1;i<=n*2;i++)
s1.append(String.format("%-4d", a[i]));
s1.append("]");
System.out.print(s1.toString());
System.out.println();
s1.setLength(0);

return;
}

for (int i = 1; i <= n*2; i++)
{
if (b[i]==0)
{
a[step]=i;
b[i]=1;
dfs(step+1);
b[i]=0;
}
}
}

public static void main(String[] args)
{
dfs(1);
}

}

WMERP 2019-04-11
  • 打赏
  • 举报
回复
引用 35 楼 _明月 的回复:
楼主,能够讲讲你面试的是什么岗位么?


我做Java的,快2年了,做算法,感觉还是一窍不通,虽然当初大学时学过算法设计这门课。



算法这东西其实不关编程语言的事情,是和数学和统计学有关的,就像本题一样,你懂得数学和组合再会建模分析的话,用任何语言都是一样的,可以专门找些与算法有关的书籍和试题,多做多看熟练逻辑思维,等熟练后不管什么项目一看的时候头脑中马上就可以建立模型和逻辑关系就好了。
WMERP 2019-04-11
  • 打赏
  • 举报
回复
最简单的,n=4 k=2 时的组合数 为 7
3456-1278
1256-3478
1246-3578
1245-3678
1236-4578
1235-4678
1234-5678
数组AB前后对调的话就是14
WMERP 2019-04-10
  • 打赏
  • 举报
回复
n=10 k=3 时有2927种分法,如果两个数组分前后的话再*2
weixin_44891582 2019-04-10
  • 打赏
  • 举报
回复
好东西,谢谢了
DiDino 2019-04-10
  • 打赏
  • 举报
回复
我能说我看得脑壳疼吗
wdonghai 2019-04-10
  • 打赏
  • 举报
回复

package jp190410;

public class MyClass
{
static int n = 8;
static int k=10;
static int gCount=0;
static int[] b=new int[100];
static int[] a=new int[100];

public static void dfs(int step)
{
//if(gCount>=500) return;
if (step>n)
{
int n2=n/2;
for (int i = 1; i <=n2; i++)
{
if(Math.abs(a[i]-a[i+n2])<k) return;
}

gCount++;

StringBuffer s1=new StringBuffer();
s1.append("答案 "+String.format("%-4d",gCount)+" 数组a:[");
for(int i=1;i<=n2;i++)
s1.append(String.format("%-4d", a[i]));
s1.append("] 数组b:[");
for(int i=n2+1;i<=n;i++)
s1.append(String.format("%-4d", a[i]));
s1.append("]");
System.out.print(s1.toString());
System.out.println();
s1.setLength(0);

return;
}

for (int i = 1; i <= n*2; i++)
{
if (b[i]==0)
{
a[step]=i;
if (a[step-1]>a[step]) continue;
b[i]=1;
dfs(step+1);
b[i]=0;
}
}
}

public static void main(String[] args)
{
dfs(1);
}

}

lx3275852 2019-04-10
  • 打赏
  • 举报
回复
引用 31 楼 WMERP 的回复:
n=10 k=3 时有2927种分法,如果两个数组分前后的话再*2
确实,你说的对。我18楼的有问题,更改后确实是2927种,但算法不好,你的算法应该更好一些……

function count( i )
{
	if( i > 2*n )
    {
		++sum;
		//if( sum <= 10 ) console.log( v1, v2 );
		return;
    }
	let t =  Math.min(v1.length+1, v2.length) - 1;
	if( v1.length < n && ( t >= 0 && ( v1.length < v2.length && Math.abs( i - v2[t] ) >= k || v1.length >= v2.length ) || t < 0 ) )
    {
		v1.push( i );
		count( i + 1 );
		v1.pop();
    }
	t =  Math.min(v1.length, v2.length+1) - 1;
	if( v2.length < n && t >= 0 && ( v2.length < v1.length && Math.abs( i - v1[t] ) >= k || v2.length >= v1.length ) )
    {
		v2.push( i );
		count( i + 1 );
		v2.pop();
    }
}
var sum = 0, n = 10, k = 3;
var v1 = [1], v2 = [];
count(2);	//1已经排到v1中了
console.log( `总共${sum}种方法.` );
直接在现在这个浏览器里,按F12或ctrl+shift+i(command+option+i),打开console(控制台),把代码复制进去就可出结果。输出结果是2927。
zh1923203991 2019-04-10
  • 打赏
  • 举报
回复
好东西啊 谢谢了
_明月 2019-04-10
  • 打赏
  • 举报
回复


楼主,能够讲讲你面试的是什么岗位么?


我做Java的,快2年了,做算法,感觉还是一窍不通,虽然当初大学时学过算法设计这门课。







WMERP 2019-04-09
  • 打赏
  • 举报
回复
由于所有的数值组合都是n而且部分排序的(必须从小到大的排序比较),所以等同 从 1至2n-k数列当中拿出 n-k 个数值与剩下的数值组成新数组B,剩下的就是素组A ,AB排序后满足要求即可以成为有效解,这样编程就可以了
onOneLight 2019-04-09
  • 打赏
  • 举报
回复
学海无涯& 2019-04-09
  • 打赏
  • 举报
回复
都是大神,我一点也看不懂。求指教软件教程
cainiaozjz 2019-04-09
  • 打赏
  • 举报
回复
选出来n个数标记不能选,把每个数k范围内的数标记不能选,最后看未被标记的数是不是n。不知道对不对
weixin_44892651 2019-04-09
  • 打赏
  • 举报
回复
qq_39936465 2019-04-09
  • 打赏
  • 举报
回复
引用 13 楼 WMERP 的回复:
绝对值X应该是 k<=X<=2n-1 比如 n=4 k=2 1,2,3,4和8,5,6,7 就是符合的一种分法。???


绝对值不可能超过n,因为要分成2组n个数的队列,当绝对值超过n的话是不可能分成2组n数列的,也就是绝对值相差最大的2组数列就是1到n和n+1到2n,因为题目本身就是要求2列后排序的。
加载更多回复(14)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧