网易内推笔试算法题目(1)

来源:互联网 发布:祝你一路顺风 知乎 编辑:程序博客网 时间:2024/05/16 13:58

题目描述:

时间限制:2秒

空间限制:32768K

小有一个长度为n的整数序列,a_1,...,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。 
输入描述:
输入包括两行,第一行包括一个整数n(2 ≤ n ≤ 2*10^5),即序列的长度。第二行包括n个整数a_i(1 ≤ a_i ≤ 10^9),即序列a中的每个整数,以空格分割。
输出描述:
在一行中输出操作n次之后的b序列,以空格分割,行末无空格。
输入例子1:
41 2 3 4
输出例子1:
4 2 1 3

题目不做过多解释,很容易理解。接下来主要分析一下阶梯思路,阶梯思路最重要:

通过一个具体用例分析:

// 11// 12 21// 213 312// 3124 4213// 42135 53124// 531246 642135
不难发现,每次跨个一步就可以抵消一次反转。所以我们可以选择1,3,5,7..这种奇数方案求解,如果给的用例是偶数的话,我们可以将用例却去掉最后一个元素当做奇数个用例进行处理,最后将去掉的那个元素单独处理,实现算法如下:


public static String get(int[] nums) {sb.delete(0, sb.length());//清空StringBuilder,sb是一个静态的全局变量,优化每一次创建对象开销int n = nums.length;boolean flag = false;if (n % 2 == 0) {n = n - 1;flag = true;}sb.append(nums[0]).append("");for (int i = 1; i < n - 1; i = i + 2) {sb.append(" ").append(nums[i]);sb.insert(0, nums[i + 1] + " ");}if ((n + 1) % 2 == 0 && flag) {//处理偶数个元素的时候,丢掉的那个元素单独处理sb.append(" ").append(nums[nums.length - 1]);sb.reverse();//偶数最后一个元素需要反转一下,找个具体用例就可以验证}return sb.toString();}

兴高采烈的提交了,结果才通过百分之40的case,此刻只能想着继续优化了。通过排除上面代码分析,应该是偶数元素单独处理时候的反转浪费空间,所以思路是优化此处,优化思路是:在上面算法中,sb的第一次初始值是nums[0],如果我们用例元素是偶数个时候,我们将初始值设置为sb.append(nums[1]).append(" ").append(nums[0]);的话就可以转为奇数个元素了,这样就可以不需要使用反转了。实现代码:

public static String get1(int[] nums) {sb.delete(0, sb.length());int n = nums.length;boolean flag = false;if (n % 2 == 0) {flag = true;}int index = 0;if (flag) {sb.append(nums[1]).append(" ").append(nums[0]);index = 2;} else {sb.append(nums[0]).append("");index = 1;}for (; index < n - 1; index = index + 2) {sb.append(" ").append(nums[index]);sb.insert(0, nums[index + 1] + " ");}return sb.toString();}
提交之后吗,测试用例:百分之50 !还是复杂度高,空间超限,所以还要继续优化,思前想后可以优化的就是不再使用StringBuilder,结果再次分析具体用例的输出结果发现:

// 1// 2 1// 3 1 2// 4 2 1 3// 5 3 1 2 4// 6 4 2 1 3 5// 7 5 3 1 2 4 6
如果是奇数个元素的话,输出结果的前面半段都是奇数位置的元素输出,然后再试偶数输出,偶数个元素情况类似。按照这个思路的话,我们就可以不在使用StringBuilder保存最终的结果了,而是逐渐打印输出,最终实现代码:

import java.util.Scanner;public class Main1 {public static void main(String[] args) {Scanner cin = new Scanner(System.in);int size = cin.nextInt();int[] nums = new int[size];for (int i = 0; i < size; i++) {nums[i] = cin.nextInt();}get2(nums);}public static void get2(int[] nums) {int n = nums.length;//便于测试,由于空格不可见,所以调试时候可以使用*替代空格String space =" ";if (n % 2 == 0) {for (int i = n - 1; i > 0; i = i - 2) {System.out.print(nums[i] + space);}// 1 2 3 4 5for (int i = 0; i < n; i = i + 2) {System.out.print(nums[i]);if (i != n - 2) {System.out.print(space);}}} else {for (int i = n - 1; i >= 0; i = i - 2) {System.out.print(nums[i] + space);}// 1 2 3 4 5 for (int i = 1; i < n; i = i + 2) {System.out.print(nums[i]);if (i != n - 2) {System.out.print(space);}}}}}

百分之百的用例通过!