醉月风纯
一个即将参加校招的学渣

导航

 

1 给定字符串,要求把前面的若干个字符移到字符串的尾部

使用三段法,先反转前面字符,再反转后面字符,最后全部反转即可。

public class convert {
public static void main(String[] args) {
	String st = "abcdef";
	st = Reverse(st,0,3);
	st = Reverse(st,3,6);
	st = Reverse(st,0,6);
	System.out.println(st);
}
public static String Reverse(String st,int s,int e) {
	char[] c = st.toCharArray();
	for(int i=s;i<e/2;i++) {
		char ch = c[i];
		c[i] = c[e-i-1];
		c[e-i-1] = ch;
	}
	return String.valueOf(c);
}
}

2.求一个数组中的重复数字

主要是一行数组的输入及HashSet的用法,注意第一行不是读取一行然后第二行要读取一行时要加一个 sc.nextLine()

import java.util.Scanner;
import java.util.HashSet;
import java.util.Iterator;

public class chu {
    static HashSet<Integer> set = new HashSet<Integer>();
    static HashSet<Integer> set1 = new HashSet<Integer>();
    public static void main(String[] args) {
	// TODO Auto-generated method stub
       Scanner sc = new Scanner(System.in);
            int[] a=new int[100];
            String s = sc.nextLine();
            String[] s1 = s.split(" ");
    
            for (int i=0;i<s1.length;i++) {
	    	a[i] = Integer.valueOf(s1[i]);
            }
        
            for(int i=0;i<s1.length;i++) {
        	    if (set.contains(a[i])) set1.add(a[i]);
        	    else set.add(a[i]);
            }
        
            Iterator<Integer> it=set1.iterator();
            while(it.hasNext()) System.out.println(it.next());
   }
}

3.如何得到一个数据流的中位数?

本题的方法是使用一个最大堆和一个最小堆来维持数组中最中间的几个数字,这样就能在O(1)时间得到数组中的中位数。

import java.util.*;
public class Solution {
    PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15,new Comparator<Integer>(){
        @Override
        public int compare(Integer o1,Integer o2){
            return o2-o1;
        }
    });
    int n=0;
    public void Insert(Integer num) {
        if(n%2==0){
            if (minHeap.size()==0||num<=minHeap.peek())
                maxHeap.offer(num);
            else{
                maxHeap.offer(minHeap.poll());
                minHeap.offer(num);
            }
        }
        else{
            if (num>=maxHeap.peek())
                minHeap.offer(num);
            else{
                minHeap.offer(maxHeap.poll());
                maxHeap.offer(num);
            }
        }
        n++;
    }

   public Double GetMedian() {
        if (n%2==1) return maxHeap.peek()*1.0;
        else return (maxHeap.peek()+minHeap.peek())/2.0;
    }
}

4. 第N个丑数问题

由于丑数都是2,3,5的整数被,所以相当于给每个数一个计数器(a,b,c),每次选择当前{2a,3b,5c}中最小的数,选中某个数字就把对应的{a,b,c}加1

if (n==0) return 0;
int[] array = new int[n];
array[0]=1;

int m1=0;
int m2=0;
int m3=0;
for (int i=1;i<n;i++) {
	array[i] = Integer.min(array[m1]*2, Integer.min(array[m2]*3, array[m3]*5));
	if(array[i]==array[m1]*2) m1++;
	if(array[i]==array[m2]*3) m2++;
	if(array[i]==array[m3]*5) m3++;
}

return array[n-1];

5.把一串电话号码转化成不少于给定数目相同数字号码

固定长度的01问题,使用DFS查找满足条件的目标

public class chu {
    static int minValue = Integer.MAX_VALUE; 
    static char[] ss;
    public static void main(String[] args) {
	    Scanner sc = new Scanner(System.in);
	    int n = sc.nextInt();
	    int a = sc.nextInt();
	    char[] c = new char[n];
	
	    if(a<2 || n<2) System.out.println(0);
	    //在换行读取下一行全部元素时要使用sc.nextLine()读取换行符
	    sc.nextLine();
	    String s = sc.nextLine();
	    for(int i=0;i<n;i++) c[i] = s.charAt(i);
	
	    //把数字转换成char型时需要加上48
	    for(int i=0;i<10;i++) dfs(c,0,(char)(i+48),0,0,a);
	    System.out.println(String.valueOf(ss));
    }
    public static void dfs(char[] s,int i,char k,int sum,int num,int aa) {
	    if(num>=aa) {
		    if(sum<minValue) {
			   minValue = sum;
			   ss = s.clone();
		    }
		    //字典树的排序直接用字符串的compareTo方法
		    else if(sum==minValue) ss = String.valueOf(ss).compareTo(String.valueOf(s))==1?s:ss;
	    }
	    if(i>=s.length);
	    else {
		dfs(s,i+1,k,sum,num,aa);
	        sum = sum +Math.abs(Integer.valueOf(s[i]-k));	    
	        //对数组进行复制
	        char[] s1=s.clone();
   		        s1[i] = k;
	        dfs(s1,i+1,k,sum,++num,aa);
	    }
    }
}

6.给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。


1.设一个slow和一个fast节点,slow每次走一次,fast每次走两次,如果有环那么slow肯定在环内某一点与fast相遇。
2.设这个点与入口的顺时针距离为y,逆时针距离为z,直线距离为x。
3.由于fast的速度是slow的两倍,所以: 2(x+y)=x+y+n(y+z),其中n为未知常数,等价于 x+y=n(y+z)
4.此时把fast放到pHead处以与slow同样的速度出发,由于slow所处的位置领先fast (x+y)距离也即是n圈,那么当fast走到入口时slow同样领先fast n圈,也就证明了slow与fast在此入口处相遇且是第一次相遇。

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if (pHead==null || pHead.next==null) return null;
        ListNode slow = pHead;
        ListNode fast = pHead;
        
        do{
            if(fast.next==null) return null;
            slow = slow.next;
            fast = fast.next.next;
        }while(slow!=fast);
        
        slow =pHead;
        while(slow!=fast){
            slow = slow.next;
            fast = fast.next;
        }
        if(slow==fast) return slow;
        else return null;
    }
}

7.写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。

第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。

同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。

第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。

第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。

 public int Add(int num1,int num2) {
  while (num2!=0){ 
	int temp = num1^num2;
	num2 = (num1&num2)<<1;
	num1 = temp;
    }
    return num1;
 }

8. 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

类似的建立一个新的与要求完全一致的结构,如果能达成会比较简单

public class Solution {
    Stack<Integer> sk = new Stack<Integer>();
    Stack<Integer> sk_min = new Stack<Integer>();
    int min = Integer.MAX_VALUE;
    public void push(int node) {
        sk.push(node);
        min = Math.min(min,node);
        sk_min.push(min);
    }
    
    public void pop() {
        sk.pop();
        sk_min.pop();
        min = sk_min.peek();
    }
    
    public int top() {
        return sk.peek();
    }
    
    public int min() {
        return min;
    }
}

9. 01背包问题

建立一个物品个数与背包重量大小的状态矩阵,状态方程的转化在于是否取当前物品以及当前物品可以取的次数。

def ZeroOnePack(N, V, weight, value):
    """
    0-1 背包问题(每个物品只能取0次, 或者1次)
    :param N: 物品个数, 如 N=5
    :param V: 背包总容量, 如V=15
    :param weight: 每个物品的容量数组表示, 如weight=[5,4,7,2,6]
    :param value: 每个物品的价值数组表示, 如weight=[12,3,10,3,6]
    :return:  返回最大的总价值
    """

    # 初始化f[N+1][V+1]为0, f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值
    f = [[0 for col in range(V+1)] for row in range(N+1)]

    for i in range(1, N+1):
        for j in range(1, V+1):
            if j<weight[i-1]:  # 总容量j小于物品i的容量时,直接不考虑物品i
                f[i][j] = f[i-1][j]
            else:
                # 注意由于weight、value数组下标从0开始,第i个物品的容量为weight[i-1],价值为value[i-1]
                f[i][j] = max(f[i-1][j], f[i-1][j-weight[i-1]]+value[i-1]) # 状态方程
    max_value = f[N][V]
    return max_value

10. 盗贼间隔房间偷东西最大值问题

直接使用DP算法:

dp[i] = Math.max(df[i-1],df[i-2]+value[i]);

如果要求不能首尾相连,那么循环0到(n-2)和1到(n-1)即可。

posted on 2018-07-08 19:13  醉月风纯  阅读(122)  评论(0编辑  收藏  举报