经典笔试编程题--Java实现

1.输入一个正数n,输出所有和为n的连续正数序列。
分析:设定两个指针,min指向和为n的连续正数序列的最小值,max指向和为n的连续正数序列最大值。sum表示真正的和。
初始情况下,min、max和sum 都指向1.
当sum小于n时,max++;
当sum大于n时,min++;
当sum等于n时,输出整个序列。

public class a {
public static void getAns(int n) {
    int min = 1;
    int sum = 1;
    int max = 1;
    while(min <= n/2+1) {
        if(sum == n) {
            for(int k = min; k<=max; k++) {         
            System.out.println(k+"");
            }
            System.out.println();
            sum = sum - min;
            min ++;
            max ++;
            sum = sum+max;
        }
        if(sum > n) {
            sum = sum - min;
            min ++;
        } else {
            max ++;
            sum = sum + max;
        }
    }
}
public static void main(String[] args) {
    getAns(15);
}}

2.给定一个排好序的链表,删除链表中重复的结点,返回链表头指针。
分析:(1)链表中重复的结点不需要保留一个,要全部删除。
(2)因为相同的结点全部要删除,所以我们设定三个指针,node指向当前节点,prev指向前驱,还有一个指向后继结点。一旦遇到node和后继结点相等,就node++,知道没有重复的再移动prev.
(3)注意:头结点也可能有重复,所以也可能被删除,所以需要定义一个root指向头结点。

public class a {
    // 结点定义,包括当前结点的值和next指向
    private static class ListNode {
        private int val;
        private ListNode next;

        public ListNode() {
        }

        public ListNode(int val) {
            this.val = val;
        }

        public String toString() {
            return val + "";
        }
    }

    // 删除节点的函数
    public static ListNode delete(ListNode head) {
        if (head == null)
            return null;
        if (head.next == null)
            return head;
        // 定义一个临时的头结点,因为头结点也可能被删除
        ListNode root = new ListNode();
        root.next = head;
        ListNode prev = root;
        ListNode node = head;

        while (node != null && node.next != null) {
            if (node.val == node.next.val) {
            //若有连续相同的结点,则node要一直++
      while (node.next != null && node.next.val == node.val)
                    node = node.next;
                prev.next = node.next;
            } else {
                prev.next = node;
                prev = prev.next;
            }
            node = node.next;
        }
        return root.next;
    }
    //打印出来删除后的结果
    private static void print(ListNode head) {
        while (head != null) {
            System.out.print(head + "->");
            head = head.next;
        }
        System.out.println("null");
    }

    public static void main(String[] args) {
        // 按照结点的定义新建一个链表
        ListNode n1 = new ListNode(1);
        ListNode n2 = new ListNode(1);
        ListNode n3 = new ListNode(2);
        ListNode n4 = new ListNode(2);
        ListNode n5 = new ListNode(2);
        ListNode n6 = new ListNode(3);
        ListNode n7 = new ListNode(5);

        n1.next = n2;
        n2.next = n3;
        n3.next = n4;
        n4.next = n5;
        n5.next = n6;
        n6.next = n7;
        n7.next = null;
        //调用delete函数,传入n1的值,当成头结点
        ListNode result = delete(n1);
        print(result);

    }
}

3.对于一个有序数组,我们通常采用二分查找的方式来定位某一元素,请编写二分查找的算法,在数组中查找指定元素。
给定一个整数数组A及它的大小n,同时给定要查找的元素val,请返回它在数组中的位置(从0开始),若不存在该元素,返回-1。若该元素出现多次,请返回第一次出现的位置。
分析:重点在返回第一次出现的位置。

public class c {
    public static int getPos(int[] A, int n, int val) {
        int low = 0, high = n - 1, mid;
        if (n == 0 || A == null)
            return -1;
        while (low <= high) {
            mid = (low + high) / 2;
    //当第一次找出相等的位置后需要继续向前查找,最后返回第一次出现的位置
            if (val == A[mid]) {
                for(int j = mid; j >= 0; j--) {
                    if(A[j] != A[mid]) {
                        mid = j + 1;
                        break;
                    }
                    else if(A[j] == A[mid]) {
                        mid = j;
                        continue;
                    }
                }
                return mid;

            } else if (val < A[mid])
                high = mid - 1;
            else
                low = mid + 1;
        }
        return -1;
    }

    public static void main(String[] args) {
        int A[] = { 4, 4, 5, 5, 5, 5 };
        int val = 4;
        int n = A.length;
        int result = getPos(A, n, val);
        System.out.println(result);
    }
}

4.对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符。
给定一个字符串(不一定全为字母)A及它的长度n。请返回第一个重复出现的字符。保证字符串中有重复字符,字符串的长度小于等于500。

方法1:这是前辈给出的算法,利用HashSet的特性,即不允许重复放入元素,所以一旦检测到重复元素就返回false。对于本道题来说,这种方法简洁且容易理解,能高效实现功能,但是这种方法普适性较差。


import java.util.HashSet;

public class g {
    public static char findFirstRepeat(String A, int n) {
        HashSet hs=new HashSet();
        int length=A.length();
        //利用toCharArray()将String类型转化为char类型
        char[] a=A.toCharArray();
        for(int i=0;i < length;i++)
            {
            boolean b=hs.add(a[i]);//通过往hashset塞值(hashset不准有重复元素),判断当前一段数据中是否有重复元素,一但有,立刻返回
                if(b==false)
                {
                 return a[i];
            }
        }
        return'0';
    }
    public static void main(String[] args) {
        String A = "qywyer23tdd";
        int n = A.length();
        char b = findFirstRepeat(A, n);
        System.out.println(b);
    }
}

方法2:利用了哈希存储,将给定字符串以键值对形式存储在哈希Map中,key就是每一个字符,value就是每个字符出现的次数。存好后再按顺序遍历Map,找出第一次出现次数不为1的即可。返回。
注意:基于hash的存储是很高效的一种方式,存储键值对方便查找,可以根据key查找value,或者根据value查找key,或者查找特殊的字符等。

延伸:返回第一个只出现一次的字符,返回最后一个出现次数不为1的字符,返回所有出现次数为1的字符或者出现次数不为1的字符,返回给定出现次数的字符等等。

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class g {
    private static void findFirstRepeat(String A, int n) {
        int sum = 1;//新插入的key-value给value赋初始值都为1
        //用LinkedHashMap来存储键值对
        //HashMap插入和输出顺序不一样
        //但LinkedHashMap插入和输出顺序相同,即先存的先显示,也就是尾插
//HashSet要求不能存重复元素,但HashMap和LinkedHashMap可以存重复元素。
             Map<String, Integer> hashMap = new LinkedHashMap
                                        <String, Integer>();
        for (int i = 0; i < n; i++) {
    //将main中传过来的String类型参数一个字符一个字符的转化为char类型,方便处理。
            char item = A.charAt(i);
//再将每一个char类型的字符转化为String类型。这一步操作和上一步操作作用是分离出每一个字符。
            String item2 = String.valueOf(item);
            String key = item2;
            // 判断是否包含指定的键值
            boolean contains = hashMap.containsKey(key);    
            if (contains) { // 如果条件为真
                sum++;
                hashMap.put(item2, sum);// 输出信息         
            } else {
                sum = 1;
                hashMap.put(item2, sum);            
            }
        }   
        //输出存进哈希表中的所有键值对
         System.out.println(hashMap);
         //以下是通过给定的value值反查key的过程
         //将所有的键值对存在一个entrySet中
         //遍历entrySet,若找到value等于给定的value值,则将其对应key值存在keyList中。
         List<String> keyList = new ArrayList<String>();  
            for (Entry<String, Integer> e : hashMap.entrySet()) {  
                if (e.getValue().equals(2)) {  
                    keyList.add(e.getKey());  
                }  
            }  
            //最后遍历keyList,输出第一次出现的key即可。
            for (String i : keyList) {  
                System.out.println(i);
                break;
            } 
    }
    public static void main(String[] args) {
        String A = "qywyer2333333333tdd";
        int n = A.length();
        findFirstRepeat(A, n);      
    }
}

关于类型转化问题:

(1)String---------》char / char[ ]
String str = "ab";
char str1 = str.charAt(0);  //得到a
char str2 = str.charAt(1);  //得到b

char[ ] str3 = str.toCharArray();
System.out.println (Arrays.toString(str3));

(2)char / char[]-----------》String
char m = 'a';
String str = String.valueOf(m);
String str2 = m + " ";

char[] m = {'a','b'};
String str3 = String.copyValueOf(m);
String str4 = new String(m);

(3)int -----------》 String
int i;
String s = String.valueOf(i);
String s = Integer.toString(i);
String s = "" + i;

(4)String ----------》 int

int i = Integer.parseInt([String]); 
i = Integer.parseInt([String],[int radix]);
int i = Integer.valueOf(my_str).intValue();

关于哈希存储的处理方案(本人亲试!) :

(1)根据key来查找,判断是否包含给定的key。
         boolean contains = hashMap.containsKey(key); 
            if (contains) { // 如果条件为真
                System.out.println("存在"+key);
            } else {
                System.out.println("不存在" + key);
            }
(2)根据value来查找,判断是否包含给定的value.
  boolean contains = hashMap.containsValue(Value); 
            if (contains) { // 如果条件为真
                System.out.println("存在"+value);
            } else {
                System.out.println("不存在" +value);
            }
(3)利用keySet遍历所有的key值。

for (Object key : hashMap.keySet()) {
System.out.println("key= " + key + " value " + hashMap.get(key));
    }
牛课网经典例题

1.合并两个排序的链表
思路:定义两个指针,一个指向list1,一个指向List2,定义一个新链表,List1和list2中哪个小就复制到新链表中。注意判断list1和list2是否为空!!!
本题是利用递归来实现的。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
       if(list1 == null) {
           return list2;
       } 
       if(list2 == null) {
           return list1;
       } 
       ListNode s = null;
        if(list1.val < list2.val) {
             s = list1;
           s.next =  Merge(list1.next, list2);
        } else if(list1.val >= list2.val) {
            s = list2;
            s.next = Merge(list1, list2.next);
        }
        return s;
    }
}

处理二进制问题:
两个int32整数m和n的二进制表达,有多少个位(bit)不同么?
(1)m^n后,将结果赋值给一个String类型的变量,循环遍历变量的每一位,看是否等于1.
(2)m^n后,将二进制结果的最后一位&1,然后将二进制右移。

public class Solution {
    /**
     * 获得两个整形二进制表达位数不同的数量
     * 
     * @param m 整数m
     * @param n 整数n
     * @return 整型
     */
    public int countBitDiff(int m, int n) {

        int x = m^n;
        int y = 0;
        while(x>0) {
            if((x&1) == 1) {
                y+=1;
            }
           x= x>>1;
        }
        return y;
    }
}

水仙花问题:水仙花,即给定一个三位数,每一位的数字立方加起来等于这个数本身。
解析:

import java.util.Scanner;
public class Solution {
         public static void main(String[] args) {
         Scanner san = new Scanner(System.in);
         //从键盘输入最小值
         int min = san.nextInt();
         //从键盘输入最大值
         int max = san.nextInt();
         for(int mid = min; mid < max; mid++) {
         int a = mid/100;
         int b = mid%10;
         int c = mid%100/10;
         int sum = a*a*a + b*b*b + c*c*c;
         if(sum == mid) {
         System.out.println(mid);
         }
         }
         }
}

题目:从键盘输入m和n,定义n是第一个数,之后的每个数都是前一个的平方根
,一共有m个数,计算总和。

import java.lang.Math;
import java.util.Scanner;

public class a {
    public static void main(String[] args) {
        //求平方根 
        Scanner scan = new Scanner(System.in);
        float n = scan.nextFloat();
        int m = scan.nextInt();
        float sum = n;
        for(int i=2;i<=m;i++) {
             sum += Math.sqrt(n);
             n = (float) Math.sqrt(n);
        }
        System.out.println("sum=" +sum);
    }
}

题目:Java的一维数组在不知道长度的情况下怎样声明?

(1) 不知道长度,所以不能直接声明大小
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class a {
    public static void main(String[] args) {
    //用ArrayList来实现添加数据
        List list = new ArrayList(); 
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入数组");
        //给定一个while循环
        //保证输入一串数字,直接接收,并添加到list中,当输入0时结束输入
        while(true) {
        int a = scanner.nextInt();
        if(a==0) {
            break;
        } else {
            list.add(a) ;
        }
        }
        int size = list.size();
        //将list转成int型数组
        Integer[] array = (Integer[])list.toArray(new Integer[size]);   
        //输出int型数组。
        for(int i=0;iout.print(array[i]+" "); 
        } 
    }
}

这样就得到一个从键盘输入的Int型数组,接下来就可以对数组进行各种操作。
符合一般情况下的需要多组测试用例的情况。

题目:给定一个正整数,编写程序计算有多少对质数的和等于这个输入的正整数,并输出结果,输出值小于1000.
测试用例:
输入:10
输出:2 ((3,7) 和(5,5))。


import java.util.Scanner;

public class cc {

    private static int cout(int number) {
        int count = 0;
        for (int i = 2; i < number; i++) {
            for (int j = 2; j <= number / 2; j++) {
                if (isPrime(i) && isPrime(j) && (i + j) == number) {
                    count++;
                }
            }
        }
        return count;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入给定的数字");
        int a = scanner.nextInt();
        int count = cout(a);
        System.out.println("count=" + count);

    }

    public static boolean isPrime(int number) {
        if (number < 2) {
            return false;
        }
        for (int i = 2; i < number; i++) {
            if (number % i == 0) {
                return false;
            } else {
                continue;
            }
        }
        return true;
    }
}

2 . 题目:二分查找,在左区间输出0,右区间输出1.
逐渐逼近,保留6位。
注意特殊输入:
(1) key值小于输入临界最小值或者大于临界最大值。
(2) 临界最小值大于临界最大值。
(3) 两个临界值都为0,输出0。



import java.util.Scanner;

public class cc {

    public static int comp(int key, int num) {
        if (key >= num) {
            return 1;
        } else {
            return 0;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入最小临界值");
        int a = scanner.nextInt();
        System.out.println("请输入最大临界值");
        int b = scanner.nextInt();
        System.out.println("请输入需要比较的值");
        int key = scanner.nextInt();
        if (key < a || key > b) {
            System.out.println("error");
        } else if (key == 0 && a == 0 && b == 0) {
            System.out.println("error");
        } else {
            while (a <= b) {
                for (int i = 0; i < 6; i++) {
                    int num;
                    num = (a + b) / 2;
                    System.out.println("num=" + num);
                    int s = comp(key, num);
                    if (s == 0) {
                        b = num;
                        System.out.println("0");
                    } else {
                        a = num;
                        System.out.println("1");
                    }
                }
                break;
            }
        }

    }
}

题目:镜像字符串,给定两个字符串,判断第二个是否为第一个的镜像字符串,是返回yes,否返回no.

import java.util.Scanner;

public class b {

    public static Boolean count(String str1, String str2) {
        int p1 = 0;
        int p2 = 0;
        char[] st1 = str1.toCharArray();
        char[] st2 = str2.toCharArray();
        for (int i = 0; i < st1.length; i++) {
            if (st1[i] == st2[0]) {
                p1 = i;
            }
        }

        while (p1 < st1.length && p2 < st2.length) {
            if (st1[p1] == st2[p2]) {
                if (p1 == st1.length) {
                    p1 = -1;
                }
                p1++;
                p2++;
                continue;
            } else {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入字符串");
        String str1 = scanner.next();
        String str2 = scanner.next();
        if(str1.length()-str2.length()!=0) {
            System.out.println("no");
            return;
        }
        if (str1 == null || str1.length() <= 0 || str2 == null
                || str2.length() <= 0) {
            System.out.println("error");
        }
        Boolean num = count(str1, str2);
        if (num.equals(true)) {
            System.out.println("yes");
        } else {
            System.out.println("no");
        }
    }
}

你可能感兴趣的:(java,哈希法,算法)