面试的一些算法小总结,根据网上现有资源和自己实际运行的结果整合到一起,希望面试的小伙伴都能顺利
1.将两个有序数据合并成一个有序数据:
public int [] sort (int[] a,int[] b){ int result[] = new int[a.length+b.length]; int i=0,j=0,k=0; while (i<a.length&&j<b.length){ if(a[i]<=b[j]){ result[k++]=a[i++]; }else { result[k++]=b[j++]; } } while (i<a.length){ result[k++]=a[i++]; } while (j<b.length){ result[k++]=b[j++]; } return result; }
2.合并两个有序数据到其中一个数组中:
有两个排序数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2,请实现一个函数,把A2中的所有数字插入到A1中并且所有的数字是有序的。
public int []mergeSort(int[]a,int lengtha,int[]b,int lengthb){ int i1 = lengtha-1; int i2 = lengtha+lengthb-1; int j = lengthb-1; while(i1>=0&&j>=0){ if(a[i1]>=b[j]){ a[i2--] = a[i1--]; }else { a[i2--] = b[j--]; } } while(j>=0){ a[i2--] = b[j--]; } return a; }
两个方法的测试:
public static void main(String[] args) { Sort sort = new Sort(); int a[]={1,2,4,5,7}; int b[]={2,3,4,6}; int lengtha = 5; int lengthb = b.length; int c[] =new int[10]; c[0]=1; c[1]=2; c[2]=4; c[3]=5; c[4]=7; int result[]=new int[a.length+b.length]; System.out.println("开始啦"); result= sort.sort(a,b); for(int x:result){ System.out.print(x); } System.out.println(); for(int y:sort.mergeSort(c,lengtha,b,lengthb)){ System.out.print(y); } }
3.java输入一个字符串,使用递归输出所有可能的排列,如输入abc,输出所有可能的结果
public static void possibleStrings(int maxLength, char[] alphabet, String curr) { // 如果递归到最大长度,则打印 if(curr.length() == maxLength) { System.out.println(curr); // 否则继续递归,从输入的字母中一次添加,构成新的组合后输出 } else { for(int i = 0; i < alphabet.length; i++) { //for循环从0到最大长度 String oldCurr = curr;//保存当前的组合字符串 curr += alphabet[i]; //继续追加 possibleStrings(maxLength,alphabet,curr);//递归:重新计算是否达到最大长度,如果达到就打印出来。 curr = oldCurr;// 保存旧值到当前字符串中 } } } //2、调用测试: public static void main(String[] args) { // 模拟输入的字母,这里假设a、b、c char[] alphabet = new char[] {'a','b','c'}; // 找出所有的abc的排列组合 Char.possibleStrings(3, alphabet,""); }
4.定义 abc bca cab 为环形相似的字符串,请写出一个函数,传入两个字符串判断这两个字符串是否为环形相似字符串,并计算时间负责度
1)将字符串转换成链表
public static Node strToNode(String s1){ char[] a1 = s1.toCharArray(); Node node = new Node(a1[0]); Node node1 = new Node('-'); //HashMap<Integer,Node> ns = new HashMap<Integer,Node>(); for (int i = 1;i<a1.length;i++){ if (i==1){ node1 = new Node(a1[i]); node.next = node1; }else if (i>1&&i<a1.length-1){ Node node2 = new Node(a1[i]); node1.next = node2; node1 = node1.next; }else{ Node node3 = new Node(a1[i]); node1.next = node3; node3.next = node; } } // if (hasLoop2(node)){ // int n = 0; // while (node !=null){ // if (ns.get(n)!=null){ // break; // } // ns.put(n,node); // node = node.next; // n++; // } // return node; // } return node; }
2)比较是否相似
public static boolean cycleChar(Node node,String s2){ char []char2 = s2.toCharArray(); int flag = 0; while (flag<char2.length){ if (node.data == char2[0]){ for (int i = 1;i<char2.length;i++){ if (node.next.data!=char2[i]){ return false; }else { node = node.next; } flag++; } } node = node.next; } return true; }
3)测试:
public static void main(String[] args) { System.out.println(hasLoop2(n1)); String s1 = "abcdc"; String s2 = "cdcab"; System.out.println("开始执行"); Node node = strToNode(s1); System.out.println("现在要比较了"); System.out.println(cycleChar(node,s2)); }
4)备注链表的类定义:
public class Node { public char data; //节点存储的数据对象 public Node next; //指向下一个节点的引用 public Node(char data){ this.data=data; } }
5.判断一个链表有没有环:
方法一:
public static boolean hasLoop(Node n){ //定义两个指针tmp1,tmp2 Node tmp1 = n; Node tmp2 = n.next; while(tmp2!=null){ char d1 = tmp1.data; char d2 = tmp2.data; if(d1==d2)return true;//当两个指针重逢时,说明存在环,否则不存在。 tmp1 = tmp1.next; //每次迭代时,指针1走一步,指针2走两步 tmp2 = tmp2.next.next; if(tmp2 == null)return false;//不存在环时,退出 } return true; //如果tmp2为null,说明元素只有一个,也可以说明是存在环 }
方法二:
public static boolean hasLoop2(Node n){ //将每次走过的节点保存到hash表中,如果节点在hash表中,则表示存在环 Node temp1 = n; HashMap<Node,Node> ns = new HashMap<Node,Node>(); while(n!=null){ if(ns.get(temp1)!=null)return true; else ns.put(temp1, temp1); temp1 = temp1.next; if(temp1 == null)return false; } return true; }
测试是否有环:
public static void main(String[] args) { Node n1 = new Node('a'); Node n2 = new Node('b'); Node n3 = new Node('c'); Node n4 = new Node('d'); Node n5 = new Node('e'); n1.next = n2; n2.next = n3; n3.next = n4; n4.next = n5; n5.next = n1; //构造一个带环的链表,去除此句表示不带环 System.out.println(hasLoop(n1)); System.out.println(hasLoop2(n1)); }
6.“给定一个字符串,找出这个字符串中出现最多的字符和次数”
public static void findChar(String s){ //将字符串存进map里key为字符串的每一个字符,value为出现的次数 HashMap<String,Integer> map = new HashMap<String,Integer>(); if (s==null){ return; } int count = 0; String base = " "; for (int i = 0;i<s.length();i++){ String word = String.valueOf(s.charAt(i)); if (!map.containsKey(word)){//没添加过map里的新建键值对 map.put(word,1); }else{ Integer integer = map.get(word)+1;//添加过map的需要将出现次数+1 map.put(word,integer); if (integer>count){ count = integer; base = word; } } } System.out.println("字母:"+base); System.out.println("次数:"+count); } //测试 public static void main(String[] args) { String s = "abcbbcaaabaccaaacbd"; findChar(s); }
7.创建一个单链表
public class MyLinkedList { public NodeInt head; public NodeInt current; public void add(int data) { //如果头结点为空,为头结点 if(head == null) { head = new NodeInt(data); current = head; } else { current.next = new NodeInt(data); current = current.next; } } //打印链表 public void print(NodeInt node) { if(node == null) { return; } current = node; while(current != null) { System.out.print(current.data + " "); current = current.next; } } //初始化链表,并且返回表头 public NodeInt init() { for(int i=0; i<10; i++) { this.add(i); } return head; } //求链表长度 public int get_length(NodeInt head) { if (head == null) { return -1; } int length = 0; current = head; while(current != null) { length++; current = current.next; } return length; } public static void main(String[] args) { MyLinkedList list = new MyLinkedList(); NodeInt head = list.init(); list.print(head); int length = list.get_length(head); System.out.println(); System.out.println("The length of list is: " + length); } } //**备注** NodeInt类的定义: public class NodeInt { public int data; //节点存储的数据对象 public NodeInt next; //指向下一个节点的引用 public NodeInt(int data){ this.data=data; } }
8.将给定的单向链表进行翻转,头变尾,尾变头
使用了7的单链表
方法一:切断链表原来的顺序
/*
1.先找到原链表的下一个元素记录存好
2.切断原来链表的链接顺序,将新的链表头(其实此时还是上一个节点,第一次是空)赋给新的current.next其实
3.当前链表节点赋给新表头
4.将下一个节点赋给当前节点,即链表往下走
*/
public static NodeInt reversed_linkedlist(NodeInt head) { // MyLinkedList list = new MyLinkedList(); // NodeInt head = list.init(); if(head == null || head.next == null) { return head; } //使用三个节指针 NodeInt current = head; NodeInt newHead = null; NodeInt next = null; while(current != null) { next = current.next;//先将当前节点的下个节点保存 current.next = newHead; //将原来的链表断链,将current的下一个结点指向新链表的头结点 newHead = current; //将current设为新表头 current = next; //将之前保存的next设为下一个节点 } return newHead; }
方法二:
使用栈的先进后出的方式:
public static void rev_tra_no_recur(NodeInt head) { if(head == null) { return; } Stack<NodeInt> stack = new Stack<>(); NodeInt current = head; while(current != null) { stack.push(current); current = current.next; } while(!stack.isEmpty()) { System.out.print(stack.pop().data + " ");//栈先进后出 } } //测试main方法: public static void main(String[] args) { MyLinkedList list = new MyLinkedList(); NodeInt head = list.init(); System.out.println(); rev_tra_no_recur(head); //reversed_linkedlist方法输出 System.out.println(); NodeInt head2 = reversed_linkedlist(head); System.out.println("After reversed, the list is: "); list.print(head2); }
9.如何判断一个ip是否合法,使用正则的方式:
/** * 判断IP地址的合法性,这里采用了正则表达式的方法来判断 * return true,合法 * */ public static boolean ipCheck(String text) { if (text != null && !text.isEmpty()) { // 定义正则表达式 String regex = "([1-9]|[1-9][0-9]|1\\d\\d|2[0-4]\\d|25[0-5])\\." + "([1-9]|[1-9][0-9]|1\\d\\d|2[0-4]\\d|25[0-5])\\." + "([1-9]|[1-9][0-9]|1\\d\\d|2[0-4]\\d|25[0-5])\\." + "([1-9]|[1-9][0-9]|1\\d\\d|2[0-4]\\d|25[0-5])"; // 判断ip地址是否与正则表达式匹配 if (text.matches(regex)) { return true; // 返回判断信息 //return text + "\n是一个合法的IP地址!"; } else { return false; // 返回判断信息 //return text + "\n不是一个合法的IP地址!"; } } return false; // 返回判断信息 // return "请输入要验证的IP地址!"; } //测试方法 public static void main(String[] args) { String ip = "233.221.105.225"; System.out.println(ipCheck(ip)); }
10.拼接两个字符串:
public static void strAppend(String s1,String s2){ StringBuffer stringBuffer = new StringBuffer(s1); StringBuffer stringBuffer1 = new StringBuffer(s2); StringBuffer result = stringBuffer.append(stringBuffer1); System.out.println(result); }
11.查找字符串中只出现一次的字符
public Character firstNotRepeating(String str){ if(str == null) return null; char[] strChar = str.toCharArray(); LinkedHashMap<Character,Integer> hash = new LinkedHashMap<Character,Integer>(); for(char item:strChar){ if(hash.containsKey(item)) hash.put(item, hash.get(item)+1); else hash.put(item, 1); } for(char key:hash.keySet()) { if(hash.get(key)== 1) return key; } return null; } public static void main(String[] args){ String str = "abaccdebff"; E35FirstNotRepeatingChar test = new E35FirstNotRepeatingChar(); System.out.println(test.firstNotRepeating(str)); }
12.给字符数组进行排序
public static String[] Compare(String str []){ for(int i= 0;i<str.length-1;i++){ for(int j = 0;j<str.length-i-1;j++){ String pre = str[j]; String next = str[j+1]; if (isMorethan(pre,next)){ String temp = pre; str[j] = next; str[j+1] = temp; } } } return str; } public static boolean isMorethan(String str1,String str2){ char[] char1 = str1.toCharArray(); char[] char2 = str2.toCharArray(); int minSize = Math.min(char1.length,char2.length); for (int i = 0 ;i<minSize;i++){ if ((int)char1[i]>(int)char2[i]){ return true; }else if((int)char1[i]<(int)char2[i]){ return false; } } if (char1.length>char2.length){ return true; } return false; } public static void main(String[] args) { String[] keys = Compare(new String[]{"fin","abc","shidema","shide","bushi"}); for (String str :keys){ System.out.println(str); } }
13.去除数组中重复元素
import java.util.HashSet; import java.util.Set; /** * Created by leige on 2019/3/2. */ public class DeleteValue { public int[] delete(int a[]){ int i,j; for(i=0,j=1;j<a.length;j++){ if (a[i]!=a[j]){ a[++i]=a[j]; } } int newArray[]=new int[i+1]; System.arraycopy(a,0,newArray,0,i+1); return newArray; } public static Object[] deduplicate4(int[] array) { if (array==null||array.length==0) { return null; } Set<Integer> set=new HashSet<Integer>(); for (int i=0; i<array.length; i++) { set.add(array[i]); } return set.toArray(); } public static void main(String[] args) { DeleteValue deleteValue =new DeleteValue(); int shuzu[] ={1,2,2,3,3,4,4,4,5}; int result[]=deleteValue.delete(shuzu); for(int a:result){ System.out.println(a); } // Object o[] = deleteValue.deduplicate4(shuzu); // for(Object a:o){ // System.out.println(a); // } } }
14.判断一个ip是否合法
/** * Created by leige on 2019/3/3. */ public class IsLegalIp { //方法一:正则表达式 public static boolean ipCheck(String str) { if (str != null && !str.isEmpty()) { // 定义正则表达式 //^和$分别表示正则表达式的开始和结束 //d表示0-9的数字 //d{2}表示两个dd,既表示这两个都是0-9的数字 String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; // 判断ip地址是否与正则表达式匹配 if (str.matches(regex)) return true; else return false; } return false; } //方法二:拆分成字符串数组判断 public static boolean ipCheck2(String str) { if(str==null||str.length()==0) return false; String[]parts=str.split("\\.");//注意写法\\.而不是单纯. //不是4段,false if(parts.length!=4){ return false; } for (int i = 0; i <parts.length ; i++) { try{ int n=Integer.parseInt(parts[i]); //如果不在正确范围,并且考虑前导0,即 065.192.168.211 if(n<0||n>255||(n!=0 && parts[i].charAt(0)=='0')) return false; } catch(NumberFormatException e){//数字格式异常 return false; } } return true; } public static boolean isIpLegal(String str){ //1.检查ip是否为空 if(str == null){ return false; } //2.检查ip长度,最短为:x.x.x.x(7位),最长为:xxx.xxx.xxx.xxx(15位) if(str.length() < 7 || str.length() > 15){ return false; } //3.解决问题(1)(2): 对输入字符串的首末字符判断,如果是"."则是非法IP if(str.charAt(0) == '.' || str.charAt(str.length()-1) == '.'){ return false; } //4.按"."分割字符串,并判断分割出来的个数,如果不是4个,则是非法IP String[] arr = str.split("\\."); if(arr.length != 4){ return false; } //5.对分割出来的每个字符串进行单独判断 for(int i = 0; i < arr.length; i++){ //解决问题(3): 如果每个字符串不是一位字符,且以'0'开头,则是非法的IP,如:01.002.03.004 if(arr[i].length() > 1 && arr[i].charAt(0) == '0'){ return false; } //对每个字符串的每个字符进行逐一判断,如果不是数字0-9,则是非法的IP for(int j = 0; j < arr[i].length(); j++){ if (arr[i].charAt(j) < '0' || arr[i].charAt(j) > '9'){ return false; } } } //6.对拆分的每一个字符串进行转换成数字,并判断是否在0~255 for(int i = 0; i < arr.length; i++){ int temp = Integer.parseInt(arr[i]); if(i == 0){ if (temp < 1 || temp > 255){ return false; } } else{ if(temp < 0 || temp > 255){ return false; } } } //7.最后,如果经过前面验证都没返回到false,返回true return true; } public static void main(String[] args) { // boolean b=ipCheck("23.135.2.255"); // boolean b=ipCheck2("23.135.2.255"); // boolean b1=ipCheck("065.135.2.255"); // boolean b2=ipCheck("0.135.2.256"); boolean b=ipCheck2("23.135.2.255"); boolean b1=ipCheck2("065.135.2.255"); boolean b2=ipCheck2("0.135.2.256"); boolean b3=ipCheck2("1.135.0.255"); boolean b4=isIpLegal("1.135.0.255"); System.out.println(b); System.out.println(b1); System.out.println(b2); System.out.println(b3); System.out.println(b4); } }
15.使用一次遍历找数组第二大的数
/** * Created by leige on 2019/3/3. */ public class FindSecMax { public int findSecMax(int[] data) { int maxNum = 0; int secMaxNum = 0; // 先将前两个元素按大小分别赋给第一大和第二大的数 if (data.length < 2) return -1; if (data[0] >= data[1]) { maxNum = data[0]; secMaxNum = data[1]; } else { maxNum = data[1]; secMaxNum = data[0]; } // 从第三个开始循环,如果元素大于最大值,则最大值更新,原最大值赋给第二大值 // 如果该元素不大于最大值,且大约第二大的值,则第二大的值更新 for (int i = 2; i < data.length; i++) { if (data[i] > maxNum) { secMaxNum = maxNum; maxNum = data[i]; } else { if (data[i] >= secMaxNum) { secMaxNum = data[i]; } } } return secMaxNum; } /** * @param args */ public static void main(String[] args) { FindSecMax fsm = new FindSecMax(); int[] a = new int[] { 10, 9,9, -70000, -90000, -600000, -500000, -32769 }; System.out.println(fsm.findSecMax(a)); } }
16.M*N个方格,从左上角走到右下角,只能选择往右走或往下走,共有多少种走法
这个题目其实是一个组合问题。对方向编号,向上是0,向右是1,那么从左下角走到右上角一定要经过M 个1和N个0。这个题目可以转化为从M+N个盒子中挑出M个盒子有多少种方法。
就是C(M+N-1, N-1)。
public class MatrixTraversal { public static int getTraversal(int p, int q) { int num = 0; if (p == 1 && q == 1) { return 1; } if (p > 1) { num += getTraversal(p - 1, q); } if (q > 1) { num += getTraversal(p, q - 1); } return num; } public static void main(String[] args) { int num = getTraversal(2, 3); System.out.println(num); } }
17.如何快速判断一个非常大的二进制数是否能被3整数
使用正则表达式
reg = /^(0+|0*1((10*1)|(01*0))*10*)$/
18.字符窜依次向后移动k位,时间负责度O(1),空间复杂度O(n)
public class Reserve { public static void reservePart(String a[],int left ,int right){ String temp=""; for(int i=0;i<(right-left+1)/2;i++){ temp=a[right-i]; a[right-i]=a[left+i]; a[left+i]=temp; } } public static void rightShift(String s[],int num,int size){ reservePart(s,0,num-1); reservePart(s,num,size-1); reservePart(s,0,size-1); } public static void main(String args[]){ String [] source = {"a","b","c","d","e","f","g","h","i"}; int len=source.length; // System.out.println(len); //数字5代表的是从左边开始需要逆置的个数,这里的结果为fghiabcde rightShift(source,5,len); for (String s:source ) { System.out.println(s); } } }
18.统计字符串中重复字母的次数
public class AccountChar { public static Map<String,Integer> findChar(String s){ Map<String,Integer> map = new HashMap<String, Integer>(); if (s==null){ return map; } String word = ""; int count =0; for(int i=0;i<s.length();i++){ word=String.valueOf(s.charAt(i)); if(!map.containsKey(word)){ map.put(word,1); }else{ Integer integer=map.get(word)+1; map.put(word,integer); } } return map; } public static void main(String[] args) { String s = "abcbbcaaabaccaaacbd"; Map<String,Integer> result = new HashMap<String, Integer>(); result=findChar(s); for(String key:result.keySet()){ Integer value=result.get(key); System.out.println(key+""+value); } } }
19.一个整数数组,其中有一个元素出现的次数超过数组长度的一半,找到该元素
public class Search { public static int majority(int a[]){ int i,c,count=1; c=a[0]; for(i=1;i<a.length;i++){ if(a[i]==c){ count++; }else{ if(count>0){ count--; }else{ c=a[i]; count=1; } } } if(count>0){ for(int j=count=0;j<a.length;j++){ if(a[j]==c){ count++; } } } if(count>=a.length/2) { return c; }else{ return -1; } } public static void main(String []args){ int source[] ={2,6,6,6,6,6,6,2,2,3,1}; int i=majority(source); System.out.println(i); } }
20.
public static int[] getRandomArrayByIndex(int num,int scope){ //1.获取scope范围内的所有数值,并存到数组中 int[] randomArray=new int[scope]; for(int i=0;i<randomArray.length;i++){ randomArray[i]=i; } //2.从数组random中取数据,取过后的数改为-1 int[] numArray=new int[num];//存储num个随机数 int i=0; while(i<numArray.length){ int index=(int)(Math.random()*scope); if(randomArray[index]!=-1){ numArray[i]=randomArray[index]; randomArray[index]=-1; i++; } } return numArray; }
public class Test1 { public static void main(String[] args) { //测试--产生20个在0-30范围内的无重复的随机数 int num=20; int scope=30;//即取[0,19)中的整数 //方法一测试 int[] testArr=getRandomArrayByIndex(num, scope); System.out.println("方法一测试结果:"+Arrays.toString(testArr)); }
21.找第一个只出现一次的值
public class Solution { public int FirstNotRepeatingChar(String str) { int[] words = new int[58]; for(int i = 0;i<str.length();i++){ words[((int)str.charAt(i))-65] += 1; } for(int i=0;i<str.length();i++){ if(words[((int)str.charAt(i))-65]==1) return i; } return -1; } }
22.找出1000以内的丑数
public class UglyNumber { public static void main(String[] args) { // 把只包含因子2、3和5的数称作丑数(Ugly Number)。 //例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。 //求按从小到大的顺序的第N个丑数。 UglyNumber un=new UglyNumber(); System.out.println("输出1000以内的丑数:"); int count=1; System.out.print(1+"\t"); for (int i = 2; i <=1000; i++) { boolean b = un.uglyNumber(i); if (count==10) { System.out.println(); count=0; } if (b) { System.out.print(i+"\t"); count++; } } } private boolean uglyNumber(int n) { if (n==2||n==3||n==5) { return true; }else if (n<1) { return false; }else{ if ((uglyNumber(n/2)&&n%2==0)||(uglyNumber(n/3)&&n%3==0)||(uglyNumber(n/5)&&n%5==0)) { return true; }else { return false; } } } }