论坛首页 综合技术论坛

公司笔试算法题

浏览 36037 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (3)
作者 正文
   发表时间:2011-03-07   最后修改:2011-03-07
解题思路:
1.对数组进行全排列
2.去掉不符合条件的排列

public class Test {
	public static void main(String[] args) {
		int[] initData = { 1, 2, 3, 4, 5 };
		// 对数组进行全排列
		perm(initData, 0, initData.length);
	}

	/**
	 * 对数组进行全排列,并打印符合条件的数组(4不能在第3位,3跟5不能相连)
	 * 
	 * @param t 要排列的数组
	 * @param start 起始位置
	 * @param end 结束位置
	 */
	public static void perm(int[] t, int start, int end) {
		if (start == end) {
			// 如果4在第三位或者3跟5相连,则不打印
			if (t[2] == 4 || is3NextTo5(t)) {

			} else {
				// 打印符合条件的数据
				for (int i = 0; i < t.length; i++) {
					System.out.print(t[i]);
				}
				System.out.println();

			}
		} else {
			for (int i = start; i < end; i++) {
				int temp = t[start];
				t[start] = t[i];
				t[i] = temp;

				//递归
				perm(t, start + 1, end);

				temp = t[start];
				t[start] = t[i];
				t[i] = temp;
			}
		}
	}

	/**
	 * 判断3跟5是否相连
	 * 
	 * @param t 数组
	 * @return true or false
	 */
	public static boolean is3NextTo5(int[] t) {
		for (int i = 0; i < t.length - 1; i++) {
			if (t[i] == 3 && t[i + 1] == 5)
				return true;
		}

		for (int i = 0; i < t.length - 1; i++) {
			if (t[i] == 5 && t[i + 1] == 3)
				return true;
		}

		return false;
	}
}
0 请登录后投票
   发表时间:2011-03-07  
这样没有意思!全排列才挑出不合适的!
0 请登录后投票
   发表时间:2011-03-07  
piao_bo_yi 写道
没考虑过用无相连通图求全排列,学习了。
我的思路:递归求全排列+条件筛选,代码:
public static void permutation(int[] src, int m) {
		if (m == src.length) {
			if (src.length > 3 && src[2] != 4) {
				boolean bPrint = true;
				for (int i = 0; i < src.length - 1; i++) {
					if ((src[i] == 3 && src[i + 1] == 5)
							|| (src[i] == 5 && src[i + 1] == 3)) {
						bPrint = false;
					}
				}
				if (bPrint)
					print(src);
			}
		} else {
			for (int i = m; i < src.length; i++) {
				swap(src, m, i);
				permutation(src, m + 1);
				swap(src, m, i);
			}
		}
	}

	public static void print(int[] src) {
		for (int i = 0; i < src.length; i++)
			System.out.print(src[i]);
		System.out.println();
	}

	private static void swap(int[] src, int m, int i) {
		int t = src[m];
		src[m] = src[i];
		src[i] = t;
	}



我也觉得用递归比较好,不过递归里的else没看明白。下面是我的代码,贴出来分享,C#写的。
public static int allListNum = 0;

public void ListNum(ArrayList numList, ArrayList printList)
{
    if (numList.Count == 1)
    {
        printList.Add(numList[0]);
        if ((int)printList[0] == 4) return;
        int i, j;
        for (i = 0; i < printList.Count; i++) {
            if ((int)printList[i] == 3)
            {
                if (i - 1 >= 0) {
                    if ((int)printList[i - 1] == 5) return;
                }
                if (i + 1 <= printList.Count - 1) {
                    if ((int)printList[i + 1] == 5) return;
                }
            }
        }
        for (j = 0; j < printList.Count; j++)
        {
            Console.Write((int)printList[j]);
        }
        allListNum++;
        Console.Write(";");
        printList.Clear();
    }
    else
    {
        for (int i = 0; i < numList.Count; i++)
        {
            bool appeared = false;
            for (int j = 0; j < i; j++)
            {
                if ((int)numList[j] == (int)numList[i])
                {
                    appeared = true;
                    break;
                }
            }
            if (appeared)
            {
                continue;
            }
            ArrayList newList = new ArrayList();
            ArrayList printNewList = new ArrayList();
            newList = (ArrayList)numList.Clone();
            printNewList = (ArrayList)printList.Clone();
            printNewList.Add(numList[i]);
            newList.RemoveAt(i);
            ListNum(newList, printNewList);
        }
    }
}

好像比较耗内存。。。。第一次发帖,包涵。
0 请登录后投票
   发表时间:2011-03-07  
强强爱妍妍 写道
楼上的,2凭啥不能在6后面?


假如2在6后面 不就重复了嘛
0 请登录后投票
   发表时间:2011-03-07   最后修改:2011-03-07
楼上的貌似都没有处理两个2的重复排列问题呀。

这里给一个非递归的实现:

public class Qiz {
    
    private static final int[] ORIGINAL = {1, 2, 2, 3, 4, 5};
    private static final int LAST_P = ORIGINAL.length - 1;
    private static int s[] = new int[ORIGINAL.length];  //全排列栈

    public static void main(String[] args) {
        boolean isLast2Used = false;  //第二个2已被使用
        Set<Integer> usedNums = new HashSet<Integer>(); 
        Arrays.fill(s, -1);
        int p = 0; //当前位置
        int count = 0;  //结果计数
        do {
            int num = ++s[p];  //当前位置的取值
            
            if (num > LAST_P) {
                //回溯
                p--;
                if (p >= 0) {
                    //清空当前取值标记,注意在这里不能用num来代替s[p],因为p已经变了
                    usedNums.remove(s[p]);
                    if (s[p] == 3) {
                        isLast2Used = false;
                    }
                }
            } else {
                if (!(usedNums.contains(num) || is3NextTo5(p) || (p == 2 && ORIGINAL[num] == 4) || (num == 2 && isLast2Used))) {
                    //如果当前取值合法
                    if (p == LAST_P) {
                        //如果已找到一个解
                        System.out.print((++count) + ":");
                        for (int i : s) {
                            System.out.print(ORIGINAL[i] + " ");
                        }
                        System.out.println();
                    } else {
                        //继续搜索前先设置有关标志
                        usedNums.add(num); 
                        if (num == 3) {
                            isLast2Used = true;
                        }

                        s[++p] = -1;  //前进一个位置
                    }
                }
            }
        } while (p > -1);
    }

    private static boolean is3NextTo5(int p) {
        if (p > 0) {
            int num1 = ORIGINAL[s[p]];
            int num2 = ORIGINAL[s[p-1]];
            if ((num1 == 3 && num2 == 5) ||
                (num1 == 5 && num2 == 3)) {
                return true;
            }
        }
        return false;
    }
}
0 请登录后投票
   发表时间:2011-03-07  
2不能在6后面。很出彩的理解啊,不仔细想还想不通。
我那代码里else后面的bool变量就是处理两个2重复的问题啊~~~~
0 请登录后投票
   发表时间:2011-03-07  
kidneyball 写道
楼上的貌似都没有处理两个2的重复排列问题呀。

这里给一个非递归的实现:

public class Qiz {
    
    private static final int[] ORIGINAL = {1, 2, 2, 3, 4, 5};
    private static final int LAST_P = ORIGINAL.length - 1;
    private static int s[] = new int[ORIGINAL.length];  //全排列栈

    public static void main(String[] args) {
        boolean isLast2Used = false;  //第二个2已被使用
        Set<Integer> usedNums = new HashSet<Integer>(); 
        Arrays.fill(s, -1);
        int p = 0; //当前位置
        int count = 0;  //结果计数
        do {
            int num = ++s[p];  //当前位置的取值
            
            if (s[p] > LAST_P) {
                //回溯
                p--;
                if (p >= 0) {
                    //清空当前取值标记
                    usedNums.remove(s[p]);
                    if (s[p] == 3) {
                        isLast2Used = false;
                    }
                }
            } else {
                if (!(usedNums.contains(num) || is3NextTo5(p) || (p == 2 && ORIGINAL[s[p]] == 4) || (s[p] == 2 && isLast2Used))) {
                    //如果当前取值合法
                    if (p == LAST_P) {
                        //如果已找到一个解
                        System.out.print((++count) + ":");
                        for (int i : s) {
                            System.out.print(ORIGINAL[i] + " ");
                        }
                        System.out.println();
                    } else {
                        //继续搜索前先设置有关标志
                        usedNums.add(num); 
                        if (num == 3) {
                            isLast2Used = true;
                        }

                        s[++p] = -1;  //前进一个位置
                    }
                }
            }
        } while (p > -1);
    }

    private static boolean is3NextTo5(int p) {
        if (p > 0) {
            int num1 = ORIGINAL[s[p]];
            int num2 = ORIGINAL[s[p-1]];
            if ((num1 == 3 && num2 == 5) ||
                (num1 == 5 && num2 == 3)) {
                return true;
            }
        }
        return false;
    }
}

兄弟能不能用伪代码描述一下,我看得有点晕。。。
0 请登录后投票
   发表时间:2011-03-07   最后修改:2011-03-07
haoleng 写道
兄弟能不能用伪代码描述一下,我看得有点晕。。。


我简化一下。

这是非递归回溯求所有数字组合的一个架子,设有N个格子,每个格子的取值可能是由1到M,取值允许重复:
public class Qiz {
    private static final int LAST_P = N - 1;
    private static int s[] = new int[LAST_P];  //全排列栈

    public static void main(String[] args) {
        Arrays.fill(s, 0);  //初始化栈
        int p = 0;           //用于记录当前位置的指针
        //TODO **初始化其他标志变量**
        do {
            int num = ++s[p];  //当前位置的取值基于原来的值加1,作为当前位置取值。
            
            if (s[p] > M) { //如果当前位置的取值已经超过了最大允许取值,则回溯到上一位置
                //回溯
                p--;
                if (p >= 0) {
                    //TODO **这时指针指向前一位置,该位置的当前取值已不属于解中,清空与这个取值有关的所有标记**
                }
            } else {
                if (/**TODO 其他特殊的判断合法条件,例如如果要全排列可以加入判断当前值不能与之前已确认的值重复**/) {
                    //如果当前取值合法
                    if (p == LAST_P) {  //指针已到最后,说明找到了一个解
                        //TODO ** 做爱做的事 **
                    } else {   //当前位置取值合法,但指针未到最后,需要继续向前搜索
                        //TODO ** 当前位置的取值已经确认属于解中,继续搜索前先根据当前取值设置有关标志 **
                        s[++p] = 0;  //前进一个位置,并初始化该位置
                    }
                }
            }
        } while (p > -1);  //位置指针已经退回到起点(即第一个位置的取值已经超过M),结束
    }
}



其中用TODO **围起来的地方可以根据需要加入自己的代码。如果是全排列的话,M和N相等,并且要加入判断当前值不能与栈中已确认的值重复。

在前一楼,因为全排列的结果还要映射到用于输出的ORIGINAL集合,取值范围是0到ORIGINAL.length-1,所以用了-1作为每个位置的初始值
0 请登录后投票
   发表时间:2011-03-07  
辛苦了~~~~正在学习。
0 请登录后投票
   发表时间:2011-03-08  
看着像宝蓝德中国的题目
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics