2019多益笔试编程和面试的算法题

2019多益笔试编程和面试的算法题

        • 多益网络笔试编程题:字符串的指定位数组合
          • 原题概述(只记得大概):
          • 题目解答
        • 多益网络面试算法题:不用比较找出两数中的较大值和较小值
          • 原题概述:
          • 题目解答
        • 代码示例:

多益的笔试题中只有一道编程题,难度中等,是《剑指offer》中的题目的变形,只要稍微认真读一下题目和看过题目的原型的话,做出来应该不会太难.

不过它给的时间有点少,我记得我当时做到编程的时候大概还有20分钟左右剩下,然后看了一下题目,一下子想不出来,就回去做了前面的题目,再回来做,就忽然记起来的,但是没有剩下多少时间了,只能写个解题思路就交了。当时没想到能过笔试,毕竟编程题都没有做出来。然后迷迷糊糊就进了面试。

面试前查了一下多益网络的面试流程之类的,发现只会有一次面试(当时看到时真不敢相信),而且是视频面试,当晚就有点紧张和兴奋了,毕竟这是第三次做笔试,才进面试了。面试面经就不说了,网上很多,而且自己应该没有过(面试中算法题答不上)

接下来进入正题吧,就想记录一下多益网络的笔试编程题和面试时遇到算法题,觉得出得挺好的。

多益网络笔试编程题:字符串的指定位数组合

原题概述(只记得大概):

找出数字字符串中指定位数的最小值。组合在原来字符串中的前后顺序不能变。

例如:有字符串"1230451",要求找出两位最小的顺序组合,则结果是1(是01的组合).

有字符串"123451",要求找出两位最小的顺序组合,则结果是11.

题目解答

原型应该是《剑指offer》中的面试题28:字符串的排序中的拓展:

如果输入n个字符,则这n个字符能构成长度为1的组合、长度为2的组合、。。、长度为n的组合。求n个字符的所有的组合(所有长度)。答案


多益的这道题本质上跟《剑指offer》中的没有太大区别,只是加了一下字符串转整数之类的过程。

核心解题思路还是字符串的m位组合数,就是将字符串组合分为两部分:

第一个字符和其余的所有字符。如果组合里包含第一个字符,则下一步在所剩余的n-1个字符里选取m个字符。如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符。也就是说,我们可以把n个字符组成长度为m的组合问题分解为两个子问题,分别求n-1个字符串中长度为m-1的组合,以及求n-1个字符的长度为m的组合。这两个子问题都可以用递归的方式解决。

具体见下方代码:

多益网络面试算法题:不用比较找出两数中的较大值和较小值

原题概述:

不用比较,找出两数中的较大值和较小值。(后来面试官有提示使用加减乘除,但是我还是想不出来,因为之前没有做过这道题,虽然这道题看起来很熟悉,有时候真的需要多做算法题,没看过的题目,硬想是很难在短时间内想到)

题目解答

面试完之后,我百度了一下解答,原来是要自己定义sign函数(即利用>>>31位获取得到某个数是正数还是负数),然后可以利用sign(a-b)就可以知道,如果a大于b,则运算结果是1。如果是b大,则运算结果是0。然后还可以利用异否^1,定义flip函数,得到1的否定0,0的否定1。

这样就可以通过上面的结果乘以两数本身然后相加,如果一个的系数为0,则另一个数的为1,和则系数为1的那个数。这样可以决定返回大小值了。

其中尤其值得注意的是,还需要考虑a-b的值可能会溢出,这时候就不单单至以上说得那么简单了,还需要考虑a和b的两个数之间的正负值

参考:https://blog.csdn.net/jeanphorn/article/details/42264537
https://blog.csdn.net/u010456903/article/details/48953429

具体见下方代码:

代码示例:

import java.util.Stack;

/**
 * 多益的编程题和面试时的编程题
 *
 * @author zhangcanlong
 * @date 2019年1月12日
 */
public class DuoyiTest {

	public static void main(String[] args) {
		DuoyiTest test = new DuoyiTest();
		// 测试1
		System.out.println("测试1都是正数");
		test.findTwoNumMinAndMax(1, 100);
		// 测试2
		System.out.println("测试2,a负,b正");
		test.findTwoNumMinAndMax(-13, 100);
		// 测试3
		System.out.println("测试3");
		test.findTwoNumMinAndMax(-13, -48);
		// 测试4(溢出情况)
		System.out.println("测试4(溢出情况)");
		test.findTwoNumMinAndMax(-2147483647, 2000000);

		// 找出数字字符串中指定位数的最小值测试1
		System.out.println("找出数字字符串中指定位数的最小值测试1:" + test.findMinNum("123450231", 2));
		// 找出数字字符串中指定位数的最小值测试2
		System.out.println("找出数字字符串中指定位数的最小值测试2:" + test.findMinNum("234523", 2));
		// 找出数字字符串中指定位数的最小值测试3
		System.out.println("找出数字字符串中指定位数的最小值测试3:" + test.findMinNum("12345231", 5));
		// 找出数字字符串中指定位数的最小值测试4
		System.out.println("找出数字字符串中指定位数的最小值测试4:" + test.findMinNum("12345231", 6));

	}

	/**
	 * 找出数字字符串中指定位数的最小值,例如:有字符串"1230451",要求找出两位最小的顺序组合,则结果是01,即1.
	 * 

* 解题思路:将其转化为从长度为n的数字数组中找出m位组合即可 * * @param str * 要寻找的字符串 * @param m * 指定的位数 */ public Integer findMinNum(String str, int m) { if (str == null || str.length() <= 1 || m >= str.length()) { if (str == null) { throw new RuntimeException("字符串不能为空"); } return Integer.parseInt(str); } int[] ints = new int[str.length()]; for (int i = 0; i < str.length(); i++) { ints[i] = Integer.parseInt(String.valueOf(str.charAt(i))); } Stack stack = new Stack<>(); Integer[] mins = new Integer[1]; combinateNum(ints, 0, m, stack, mins); return mins[0]; } /** * 求数组的m位组合,递归方法 * * @param ints 要求的数组 * @param start 开始求组合的元素下标 * @param combinateDigit 要求的组合数 * @param stack 存放一次组合的结果 * @param mins 存放m个字符值的最小值,即最终结果 */ private void combinateNum(int[] ints, int start, int combinateDigit, Stack stack, Integer[] mins) { if (combinateDigit <= 0) { // 遍历获取栈,求得拼接的值的大小(这里不考虑大数范围) int tempMin = 0; for (int i = 0; i < stack.size(); i++) { tempMin = tempMin + ((int) Math.pow(10, stack.size() - i - 1)) * stack.get(i); // System.out.print(stack.get(i) + " "); } // System.out.println(); // 重新赋值最小值 if (mins[0] == null || mins[0] > tempMin) { mins[0] = tempMin; } return; } if (start > ints.length - 1) { return; } stack.push(ints[start]); combinateNum(ints, start + 1, combinateDigit - 1, stack, mins); stack.pop(); combinateNum(ints, start + 1, combinateDigit, stack, mins); } /** * 不用比较,找出两个数中最大的和最小的(不考虑溢出情况) */ public void findTwoNumMinAndMax(int a, int b) { int signA = sign(a - b); int signB = flip(signA); System.out.println("较大的数为:" + (signA * a + signB * b)); System.out.println("较小的数为:" + (signB * a + signA * b)); } /** * 取相反的数,如果是1,则返回0,如果是0,则返回1 */ private int flip(int n) { return n ^ 1; } /** * 判断某个数的符号 * * @param n * 要判断的数 * @return 如果是正数,返回1,如果是负数返回0 */ private int sign(int n) { return (n >>> 31) ^ 1; } }

你可能感兴趣的:(算法设计与分析,面试)