【算法】创新工场涂鸦移动2017校园招聘测试题-A卷-软件工程师

今天做了创新工场涂鸦移动2017校园招聘测试题-A卷-软件工程师的题目,我也不知道这算不算是泄题,再说也不见得我写的算法就是对的。贴出来,希望大家相互学习,相互进步,如有违反XX,不胜荣幸。

链表

  • 1将链表中的所有元素为奇数的节点移到元素为偶数节点的前面,并使奇数之间顺序反转,偶数之间顺序反转。

  • 示例:
    交换前链表的顺序 交换后链表的顺序
    4→5→7→1→6 ==> 1→7→5→6→4
    1 ==> 1 (链表仅含一个元素)
    2→1 ==> 1→2
    ==> (链表为空)

  • C/C++:
    链表节点定义为:
    struct node {
    struct node *next;
    int value;
    };
    struct node *swap(struct node *list);

  • Java:
    链表节点定义为:
    class Node {
    public Node next;
    public int value
    }
    Node swap(Node list)

  • 注意点和要求如下:

    1. swap函数要求对节点的指针/引用进行操作(不得创建任何新的链表节点)
    2. 不得使用任何库函数/API,如需使用类似功能, 请自行实现
    3. 不得将链表转化为其他类型数据结构再进行交换,如数组等
  • 算法思路
    本题算法不难,就是将奇数逆序排在前面,偶数逆序拍在后面,所以,毫无疑问应该是有两个头结点,一个链接奇数,一个链接偶数,将原链表从头扫描至尾部时,能分别将节点插入到奇偶链表中。

  • 代码

import java.util.Scanner;

public class Main{
    //链表结构
      static class Node {
            public Node next;
            public int value;
            public Node(){

            }
            public Node(int val){
                this.value=val;
            }
        }
        //创建以尾插入的方式创建链表
      public Node createListNode(){
             System.out.println("请输入节点值以-1结束");
             Scanner scan = new Scanner(System.in);
             Node pHead= new Node();
             int temp;
             if((temp=scan.nextInt())==-1){//头结点
                 return null;
             }else{
                 pHead.value=temp;
             }
             Node p =pHead;
             while((temp=scan.nextInt())!=-1){
                 Node q = new Node(temp);
                 p.next=q;
                 p=p.next;
             }
             p.next=null;
             return pHead;
         } 
         //打印链表
         public void display(Node pHead){
             while(pHead!=null){
                 System.out.print(pHead.value+"\t");
                 pHead=pHead.next;
             }
             System.out.println();
         }
         //链表处理
        public Node swap(Node list){
            Node p = list;
            Node qi=null;//存放奇数的链表
            Node ou=null;//存放偶数的链表
            Node pnext=null;//用于存储处理原链表当前节点的下一个节点
            while(p!=null){
                pnext=p.next;//下一个节点先存储
                if(p.value%2==1){//如果是奇数节点
                    if(qi==null){//第一个奇数节点
                        p.next=null;
                         qi=p;
                    }else{//其他奇数节点采用头插法链接到奇数链表中
                        p.next=qi;
                        qi=p;
                    } 
                }
                if(p.value%2==0){//如果是偶数节点
                    if(ou==null){//第一个偶数节点
                        p.next=null;
                        ou=p;
                    }else{//其他偶数节点采用头插法链接到偶数链表中
                        p.next=ou;
                        ou=p;

                    }
                }
                p=pnext;
            }
            list=qi;//奇数链表的头节点作为返回链表的头节点

            //遍历奇数链表
            while(qi!=null){
                pnext=qi;
                qi=qi.next;
            }
            //将偶数链表插入到奇数链表末尾
            if(pnext!=null){
                pnext.next=ou;
            }else{//如果没有奇数链表,则直接返回偶数链表
                return ou;
            }
            //返回链表头结点
            return list;
        }

           public static void main(String[] args) {
               Main cls = new Main();
                Node pHead =  new Node();//创建链表头结点
                System.out.println("创建链表");
                pHead=cls.createListNode();
                cls.display(pHead);//打印链表
                System.out.println("链表swap之后");
                pHead=cls.swap(pHead);//处理链表
                cls.display(pHead);//打印链表
            }
}
  • 结果
创建链表
请输入节点值以-1结束
4 5 7 1 6 -1
4   5   7   1   6   
链表swap之后
1   7   5   6   4

正整数n的最少平方和

给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, … )使得他们的和等于 n。你需要让平方数的个数最少。
给出 n = 12, 返回 3 因为 12 = 4 + 4 + 4。
给出 n = 13, 返回 2 因为 13 = 4 + 9。

  • 算法思路
    毫无疑问是采用动态规划。如果有人做过换零钱这种题目,估计这题也就不陌生了,就是问如果有票值为1元、2元、5元,10元,给定输入的一个钱数,用最少的纸币找清,比如12元只需要一张10元和一张2元共两张就可以找清。因此和本题都是希望能用最少的数的和等于一个数n。这题不一样的在于没有固定票值,但是稍微变通一下,试想一个数的平方和最大就是根号向下取正的那个数,比如11,开根号向下取正就是3,所以3、2、1就是找零钱里面的票值。
    采用动态规划解决这个问题,假设a[i]存储的是数i需要最少数的平方和,i=1,…,n;j为1,…,sqrt(n)状态转移公式,则a[i]=min(a[i],a[i-j*j]+1)。说明白点就是对于整数n,对于从1到n的开平方根中某个数的选择还是不选择在于最终平方和等于n的数是不是最小决定。

  • 代码

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = (int) Math.sqrt(n);
        int a[] = new int[n+1];
        for(int i=1;i<=n;i++){
            a[i]=Integer.MAX_VALUE;
            for(int j=1;j<=m&&i>=j*j;j++){
                a[i]=Math.min(a[i], a[i-j*j]+1);
            }
        }
        System.out.println(a[n]);
    }
}

总结

其实这两题算法应该都不算难,考得还是基本功,当然上面算法多有瑕疵,如有大神发现错误,望不吝赐教!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值