1、一个单词单词字母交换,可得另一个单词,如army->mary,成为兄弟单词。提供一个单词,在字典中找到它的兄弟。描述数据结构和查询过程。评点:同去年9月份的一道题,见此文第3题:http://blog.csdn.net/v_july_v/article/details/6803368。
统计每个字母出现的次数
4、算法题1
一个url指向的页面里面有另一个url,最终有一个url指向之前出现过的url或空,这两种情形都定义为null。这样构成一个单链表。给两条这样单链表,判断里面是否存在同样的url。url以亿级计,资源不足以hash。
环?
5、算法题2
数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)
插入排序
1、删除字符串开始及末尾的空白符,并且把数组中间的多个空格(如果有)符转化为1个。
package com.duoduo.test;
public class StringFilterBlank {
public static String filter(String a) {
if (a == null || a.equals("")) {
return a;
}
int N = a.length();
int M = 0;
char[] str = a.toCharArray();
// step 1:统计去白后的字符串长度M
int head = 0, tail = N - 1;
while (head < N && str[head] == ' ') {
head++;
}
while (tail >= 0 && str[tail] == ' ') {
tail--;
}
for (int i = head; i <= tail; i++) {
if (str[i] != ' ') {
M++;
} else if (str[i - 1] != ' ') {
M++;
}
}
if (M == 0) {
return "";
}
// StdOut.println(M + " N: " + N + " head: " + head + " tail:" + tail);
// 第二部 将空白除去
int index = 0;
while (index < M) {
if (str[head] != ' ') {
str[index++] = str[head++];
} else {
if (str[head - 1] != ' ') {
str[index++] = str[head++];
} else {
head++;
}
}
}
return new String(str, 0, M);
}
public static void main(String args[]) {
String[] TEST = new String[] { "abc dae bc ", " abc dae bc ",
" abc dae bc ", " abc dae bc ",
" a b c d a e b c ", "", " ", " a", "b " };
for (String str : TEST) {
System.out.println(filter(str));
}
}
}
找出两个单链表里交叉的第一个元素
问题1:如何判断俩单链表(俩单链中均无环)是否交叉?
第一条链遍历至尾部,记此结点指针为p1;第二条链也遍历至尾部,此记结点指针为p2。则若此时p1与p2相等,俩单链交叉。
问题2:如果交叉,如何找到交叉点?
若较长链表为head1。设两指针p1和p2分别对链表head1和head2从头遍历,步长均为1,让p1先移动nLen1 - nLen2步,再让p1和p2同时移动,则p1与p2相遇处即为交叉点处。
9、字符串移动(字符串为*号和26个字母的任意组合,把*号都移动到最左侧,把字母移到最右侧并保持相对顺序不变),要求时间和空间复杂度最小
从后向前遍历:
step 1、head记录星星的个数,如果为*则head++,否则a[i+head] = a[i]
step 2、将0~head位置赋值为*
http://blog.csdn.net/cxllyg/article/details/7985681
10、时间复杂度为O(1),怎么找出一个栈里的最大元素
辅助栈如图
2、线程和进程区别和联系。什么是“线程安全”
http://blog.csdn.net/gaopo_y/article/details/8080987
判断一个数字序列是BST(binary search tree)后序遍历的结果,现场写代码。
http://blog.csdn.net/hopeztm/article/category/1201028
2. 给出大小为N的数组,用最快的办法找出前M个大的数字
package com.duoduo.test;
import java.util.PriorityQueue;
public class QueueTest {
public static void main(String args[]) {
PriorityQueue<Integer> queue = new PriorityQueue<Integer>();
int[] S = new int[] { 2, 1, 4, 5, 7, 11, 2, 1, 5, 7, 8, 3, 5, 7, 8, 3,
2, 6 };
int M = 10;
int index = 0;
while (index < M) {
queue.add(S[index++]);
}
while (index < S.length) {
if (queue.peek() < S[index]) {
queue.remove();
queue.add(S[index]);
}
index++;
}
System.out.println(queue);
for (int i = 0; i < M; i++) {
System.out.print(queue.poll() + " ");
}
}
}
http://blog.csdn.net/a9529lty/article/details/4042019
package com.duoduo.test;
public class MulLR {
public static void main(String[] args) {
int[] a = { 2, 3, 4, 5 };
int N = a.length;
int[] r = new int[N];
int left, right;
for (int i = 0; i < N; i++) {
left = right = 1;
for (int j = 0; j < i; j++) {
left *= a[j];
}
for (int j = N - 1; j > i; j--) {
right *= a[j];
}
r[i] = left * right;
}
for (int i = 0; i < N; i++) {
System.out.print(r[i] + " ");
}
}
}
package com.duoduo.test;
import java.util.LinkedList;
import java.util.Queue;
public class GraphTest {
private class Graph {
private int V;
private int E;
private LinkedList<Integer>[] adj;
public Graph(int V) {
this.V = V;
this.E = 0;
adj = (LinkedList<Integer>[]) new LinkedList[V];
for (int v = 0; v < V; v++) {
adj[v] = new LinkedList<Integer>();
}
}
public void addEdge(int v, int w) {
E++;
adj[v].add(w);
adj[w].add(v);
}
public Iterable<Integer> adj(int v) {
return adj[v];
}
public String toString() {
StringBuilder s = new StringBuilder();
String NEWLINE = System.getProperty("line.separator");
s.append(V + " vertices, " + E + " edges " + NEWLINE);
for (int v = 0; v < V; v++) {
s.append(v + ": ");
for (int w : adj[v]) {
s.append(w + " ");
}
s.append(NEWLINE);
}
return s.toString();
}
}
private int count;
private boolean[] marked;
private int[] id;
private Graph G;
public GraphTest(int V, int[][] edges) {
this.marked = new boolean[V];
this.id = new int[V];
this.G = new Graph(V);
for (int[] edge : edges) {
this.G.addEdge(edge[0] - 1, edge[1] - 1);
}
for (int v = 0; v < V; v++) {
if (!marked[v]) {
dfs(v);
count++;
}
}
}
private void dfs(int v) {
marked[v] = true;
id[v] = count;
for (int w : this.G.adj(v)) {
if (!marked[w]) {
dfs(w);
}
}
}
public boolean connected(int v, int w) {
return id[v] == id[w];
}
public Graph G() {
return this.G;
}
public int count() {
return count;
}
public static void main(String[] args) {
int V = 5;
int[][] edges = { { 1, 2 }, { 2, 3 }, { 4, 5 }, { 3, 4 } };
GraphTest gt = new GraphTest(V, edges);
System.out.println(gt.G());
System.out.println(gt.count());
}
}
9月19日,创新工厂笔试题:
给定一整型数组,若数组中某个下标值大的元素值小于某个下标值比它小的元素值,称这是一个反序。
即:数组a[]; 对于i < j 且 a[i] > a[j],则称这是一个反序。
给定一个数组,要求写一个函数,计算出这个数组里所有反序的个数。
package com.duoduo.test;
public class NiXu {
private static int[] aux;
private static int count;
private NiXu() {
}
public static int count() {
return count;
}
public static void sort(int[] a) {
aux = new int[a.length];
count = 0;
sort(a, 0, a.length - 1);
}
private static void sort(int[] a, int lo, int hi) {
if (lo < hi) {
int mid = lo + (hi - lo) / 2;
sort(a, lo, mid);
sort(a, mid + 1, hi);
if (a[mid] > a[mid + 1]) {
merge(a, lo, mid, hi);
}
}
}
// lo ~ mid 应为 小序列,如果mid~hi
//以下为引用网上一哥们的解释:
// 举个例子,原序列是9 10 2 4 3
// 最后要合并的两个左右序列是2 9 10 和 3 4
// 刚开始a[i]=2 a[j] = 3,a[i]<a[j]不存在逆序对,将i++,a[i]->9
// 这时候a[i]>a[j],存在逆序对,并且前一个序列中a[i+1...mid]因为是已经排序的,
// 后面的每个数肯定也大于a[i],当然也大于a[j],当然也和a[j]成逆序对,这时候的逆序对的个数应该为mid-i+1
private static void merge(int[] a, int lo, int mid, int hi) {
for (int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
int i = lo;
int j = mid + 1;
int k = lo;
while (i <= mid && j <= hi) {
if (aux[i] <= aux[j]) {
a[k++] = aux[i++];
} else {
count += (mid - i + 1);
a[k++] = aux[j++];
}
}
while (i <= mid) {
a[k++] = aux[i++];
}
while (j <= hi) {
a[k++] = aux[j++];
}
}
public static void main(String[] args) {
int[] a = { 9, 10, 2, 4, 3 };
sort(a);
System.out.println(count());
for (int i : a) {
System.out.print(i + " ");
}
}
}
9月20日,创新工厂南京站笔试:
已知字符串里的字符是互不相同的,现在任意组合,比如ab,则输出aa,ab,ba,bb,编程按照字典序输出所有的组合。
mport java.util.Arrays;
public class QP {
private char[] a;
private int N;
private char[] b;
public QP(String str) {
a = str.toCharArray();
b = new char[a.length];
N = a.length;
Arrays.sort(a);
perm(0);
}
private void perm(int pos) {
if (pos == N) {
print(b);
} else {
for (int i = 0; i < N; i++) {
b[pos] = a[i];
perm(pos + 1);
}
}
}
private void print(char[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
System.out.println();
}
public static void main(String[] args) {
QP qp = new QP("abc");
}
}
栈即可解决
package com.duoduo.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.Map.Entry;
public class KuHao {
private final static Map<Character, Character> map;
private final static Map<Character, Character> reverse_map;
static {
map = new HashMap<Character, Character>();
reverse_map = new HashMap<Character, Character>();
map.put(')', '(');
map.put(']', '[');
map.put('}', '{');
Iterator<Entry<Character, Character>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<Character, Character> entry = iter.next();
reverse_map.put(entry.getValue(), entry.getKey());
}
}
public static boolean isValidSeq(String input) {
Stack<Character> stack = new Stack<Character>();
int N = input.length();
for (int i = 0; i < N; i++) {
char ch = input.charAt(i);
// ch 为左括号的话直接入栈
if (!map.containsKey(ch)) {
stack.push(ch);
} else {
if (stack.size() == 0) {
return false;
}
if (map.get(ch) != stack.pop()) {
return false;
}
}
}
if (stack.size() > 0) {
return false;
}
return true;
}
public static String fixSeq(String input) {
if (isValidSeq(input)) {
return input;
}
Stack<Character> stack = new Stack<Character>();
List<Character> result = new ArrayList<Character>();
int N = input.length();
for (int i = 0; i < N; i++) {
char ch = input.charAt(i);
// ch 为左括号的话直接入栈,加入结果集
if (!map.containsKey(ch)) {
stack.push(ch);
result.add(ch);
} else {
// 如果栈为空,则将对应的左括号和右括号加入结果集
if (stack.size() == 0) {
result.add(map.get(ch));
result.add(ch);
continue;
} else {
// 如果栈不为空,并且不匹配,则找到左括号然后将ch加进去
if (map.get(ch) != stack.peek()) {
result.add(map.get(ch));
result.add(ch);
} else {
// 匹配直接加入右括号
stack.pop();
result.add(ch);
}
}
}
}
while (!stack.isEmpty()) {
result.add(reverse_map.get(stack.pop()));
}
int M = result.size();
char[] r = new char[M];
for (int i = 0; i < M; i++) {
r[i] = result.get(i);
}
return new String(r);
}
public static void main(String[] args) {
String[] test = { "{}", "{{}", "{[]}", "{[{({})}]}", "{[]]}", "]]}"
};
for (String str : test) {
System.out.println(isValidSeq(str));
System.out.println(fixSeq(str));
System.out.println(" == ");
}
}
}
死锁
死锁的四个必要条件
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,改环路中每个进程都在等待相邻进程正占用的资源。