面试题2:单例模式
class SingleTon
{
public SingleTon Instance()
{
return Nested.instance;
}
private class Nested
{
internal static readonly SingleTon instance = new SingleTon();
}
}
要点:静态变量/函数只会在程序运行时执行一次。
面试题3:找出数组中重复的数字
public void Problem3()
{
HashSet result = new HashSet();
int[] input = {2,6,5,7,1,2,3,4,8};
for (int i = 0; i < input.Length; i++)
{
int value = input[i];
while (input[i] != i)
{
if (input[value] != value)
{
int temp = input[i];
input[i] = input[value];
input[value] = temp;
value = input[i];
}
else
{
result.Add(value);
break;
}
}
}
foreach (int value in result)
{
Console.WriteLine(value);
}
}
面试题3-2:在不改动原数组的前提下,找出重复的数字
public void Problem3_2()
{
int? result = null;
int num = 0;
int[] array = { 2, 3, 5, 4, 3, 2, 6, 7 };
int start = 0, end = array.Length - 1;
while (end >= start)
{
int mid = (end - start)>>1 + start;
int count = GetCount(array, start, mid);
if (end == start)
{
if (count > 1)
{
result = array[start];
num = count;
}
break;
}
if (count > (mid - start + 1))
{
end = mid;
}
else
{
start = mid + 1;
}
}
if (result == null)
{
Console.WriteLine("没有重复的数字");
}
else
{
Console.WriteLine(result + "重复了{0}次", num);
}
}
private int GetCount(int[] array, int start, int end)
{
int count = 0;
for (int i = 0; i < array.Length; i++)
{
for (int j = start; j <= end; j++)
{
if (array[i] == array[j])
{
count++;
}
}
}
return count;
}
面试题4:在二维数组中查找数字
public bool Problem4(int target)
{
int[,] input = {
{ 1,2,3},
{ 2,4,6},
{ 3,6,9},
};
bool result = false;
int col = input.GetUpperBound(0) + 1;
int row = input.GetLength(0);
//从右上开始遍历
int c = col - 1;//列
int r = 0;//行
while (c < 0 || r > row - 1)
{
int value = input[c, r];
if (value == target)
{
result = true;
break;
}
else if (value > target)
{
c--;
}
else
{
r++;
}
}
Console.WriteLine(result);
return result;
}
要点:从右上角或者左下角开始比较,才可以在每次比较中缩小查询的区域。
面试题5:将字符串中的空格提替换成指定字符
public string Problem5(string input, string target)
{
if (input.Length == 0)
{
return "";
}
int count = 0;
foreach (var c in input)
{
if (c == ' ')
{
count++;
}
}
char[] chars = new char[input.Length + count * (target.Length - 1)];
int p = chars.Length - 1;
for (int i = input.Length - 1; i >= 0; i--)
{
if (input[i] != ' ')
{
chars[p--] = input[i];
}
else
{
for (int j = target.Length - 1; j >= 0; j--)
{
chars[p--] = target[j];
}
}
}
return new string(chars);
}
要点:从后往前替换。
面试题6:从尾到头打印链表
//用栈实现
public void Problem6_1(ListNode Head)
{
if (Head == null)
{
return;
}
Stack stack = new Stack();
while (Head.Next != null)
{
stack.Push(Head.Value);
Head = Head.Next;
}
stack.Push(Head.Value);
while (stack.Count > 0)
{
Console.WriteLine(stack.Pop());
}
}
//用递归实现
public void Problem6_2(ListNode Head)
{
if (Head == null)
return;
if (Head.Next != null)
Problem6_2(Head.Next);
Console.Write(Head.Value);
}
要点:递归的本质就是栈结构。
面试题7:给定前序遍历序列和中序遍历序列输出后续遍历序列。
public void Problem7()
{
//输入前序遍历序列
int[] input1 = { 1, 2, 4, 7, 3, 5, 6, 8 };
//输入中序遍历序列
int[] input2 = { 4, 7, 2, 1, 5, 3, 8, 6 };
Tree root = Problem7_Solution(input1, input2, 0, 0, input1.Length - 1);
//输出后续遍历序列
OutPut(root);
}
private void OutPut(Tree tree)
{
if (tree == null)
return;
OutPut(tree.LeftNode);
OutPut(tree.RightNode);
Console.WriteLine(tree.Value);
}
private Tree Problem7_Solution(int[] input1, int[] input2, int root_pos, int start_pos, int end_pos)
{
if (end_pos < start_pos || root_pos > input1.Length)
return null;
Tree tree = new Tree(input1[root_pos]);
if (start_pos == end_pos)
return tree;
int i;
for (i = start_pos; i <= end_pos; i++)
{
if (input2[i] == tree.Value)
{
break;
}
}
int left_num = i - start_pos;
int LeftRootPos = root_pos + 1;
tree.LeftNode = Problem7_Solution(input1, input2, LeftRootPos, start_pos, i - 1);
int RightRootPos = root_pos + left_num + 1;
tree.RightNode = Problem7_Solution(input1, input2, RightRootPos, i + 1, end_pos);
return tree;
}
------------------------------------------------------------------------------
class Tree
{
public int Value;
public Tree LeftNode;
public Tree RightNode;
public Tree(int value) { Value = value; }
}
面试题8:二叉树的下一个节点,给定中序遍历序列找出下一个节点。
public class TreeNode
{
public TreeNode()
{
Value = "";
}
public TreeNode(string value)
{
Value = value;
}
public string Value { get; set; }
public TreeNode LeftNode { get; set; }
public TreeNode RightNode { get; set; }
public TreeNode ParentNode { get; set; }
}
----------------------------------------------------------------------------------------
public class solution
{
public TreeNode Problem8_FindNextNode(TreeNode tree, TreeNode node)
{
if (tree == null || node == null)
return null;
TreeNode result = new TreeNode();
if (node.RightNode != null)
{
result = node.RightNode;
while (result.LeftNode != null)
{
result = result.LeftNode;
}
}
else
{
if (node.ParentNode.LeftNode == node)
{
result = node.ParentNode;
}
else
{
while (node.ParentNode != null && node.ParentNode.RightNode == node)
{
node = node.ParentNode;
}
result = node.ParentNode;
}
}
Console.Write(result == null ? "" : result.Value);
return result;
}
}
面试题9:用两个栈实现队列
public class MyQueue
{
Stack stack1 = new Stack();
Stack stack2 = new Stack();
public int Count
{
get;
private set;
}
public void Clear()
{
stack1.Clear();
stack2.Clear();
Count = 0;
}
public bool Contains(T target)
{
return stack1.Contains(target) || stack2.Contains(target);
}
public T Dequeue()
{
if (Count <= 0)
{
return default(T);
}
Count--;
if (stack1.Count != 0)
{
while (stack1.Count != 0)
{
stack2.Push(stack1.Pop());
}
return stack2.Pop();
}
else
{
while (stack2.Count != 0)
{
stack1.Push(stack2.Pop());
}
return stack1.Pop();
}
}
public void Enqueue(T target)
{
Count++;
if (stack1.Count != 0)
{
stack1.Push(target);
}
else
{
stack2.Push(target);
}
}
public T[] ToArray()
{
T[] array = new T[Count];
if (stack1.Count != 0)
{
return array = stack1.ToArray();
}
else
{
return array = stack2.ToArray();
}
}
补充:用两个队列实现栈,思路:将第一个队列内的n-1个元素移动到第二个队列后,弹出队列中剩下的唯一一个元素。
面试题10:斐波那契数列
public int Problem10(int n)
{
if (n <= 0)
return 0;
if (n == 1)
return 1;
return Problem10(n - 1) + Problem10(n - 2);
}
面试题11:旋转数组的最小数字
//Problem11 旋转有一定排序的数组的最小数字 如[3,4,5,1,2] -> return 3
public int Problem11(int[] array)
{
int start = 0;
int mid = start;
int end = array.Length - 1;
if (array[start] < array[end])
{
return start;
}
while (end - start > 1 && array[start] == array[end])
{
start++;
}
while (end - start > 1)
{
mid = (start + end) / 2;
if (array[start] <= array[mid])
{
start = mid;
}
else if (array[mid] <= array[end])
{
end = mid;
}
}
return end;
}
面试题12:矩阵中的路径
//Problem12 矩阵中的路径
#region Problem12
private char[] array;
private int[,] result_index;
public bool Problem12(char[,] matrix, string target)
{
int row_length = matrix.GetLength(0);
int col_length = matrix.GetLength(1);
array = target.ToCharArray();
bool[,] visited = new bool[row_length, col_length];
result_index = new int[array.Length, 2];
bool hasPath = false;
for (int row = 0; row < row_length; row++)
{
for (int col = 0; col < col_length; col++)
{
if (FindStrInMatrix(matrix, row, col, row_length, col_length, 0, visited))
{
hasPath = true;
break;
}
}
}
Console.WriteLine(hasPath ? "Find Success" : "Find False");
if (hasPath)
{
for (int i = 0; i < result_index.GetLength(0); i++)
{
for (int j = 0; j < 2; j++)
{
Console.Write(result_index[i, j] + " ");
}
Console.WriteLine();
}
}
return hasPath;
}
public bool FindStrInMatrix(char[,] matrix, int row, int col, int row_length, int col_length, int char_index, bool[,] visited)
{
if (char_index >= array.Length)
{
return true;
}
bool result = false;
if (row >= 0 && col >= 0 && row < row_length && col < col_length && matrix[row, col] == array[char_index] && !visited[row, col])
{
visited[row, col] = true;
result_index[char_index, 0] = row;
result_index[char_index, 1] = col;
char_index++;
result = FindStrInMatrix(matrix, row - 1, col, row_length, col_length, char_index, visited)
|| FindStrInMatrix(matrix, row + 1, col, row_length, col_length, char_index, visited)
|| FindStrInMatrix(matrix, row, col - 1, row_length, col_length, char_index, visited)
|| FindStrInMatrix(matrix, row, col + 1, row_length, col_length, char_index, visited);
if (!result)
{
char_index--;
visited[row, col] = false;
result_index[char_index, 0] = 0;
result_index[char_index, 1] = 0;
}
}
return result;
}
#endregion
面试题13:机器人的运动范围
#region 机器人的运动范围
public void Problem13(int m, int n, int k)
{
if (m <= 0 || n <= 0)
{
return;
}
visited = new bool[m, n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
visited[i, j] = false;
}
}
Console.WriteLine(Move(0, 0, m, n, k));
}
private bool[,] visited;
private int Move(int i, int j, int m, int n, int k)
{
if (!Check(i, j, m, n, k))
{
return 0;
}
if (visited[i, j])
{
return 0;
}
visited[i, j] = true;
int count = 1;
//向上
count += Move(i, j - 1, m, n, k);
//向下
count += Move(i, j + 1, m, n, k);
//向左
count += Move(i - 1, j, m, n, k);
//向右
count += Move(i + 1, j, m, n, k);
return count;
}
private bool Check(int i, int j, int m, int n, int k)
{
if (i < 0 || j < 0 || i >= m || j >= n)
{
return false;
}
int total = i % 10 + i / 10 + j % 10 + j / 10;
Console.WriteLine("i:{0},j:{1},total:{2}", i, j, total);
return k >= total;
}
#endregion
面试题14:剪绳子 长度为n的绳子 剪成若干单位为1的绳 求长度乘积最大的值
#region Problem14
//动态规划
public int Problem14_1(int length)
{
if (length <= 1) return 0;
if (length == 2) return 1 * (2 - 1);
if (length == 3) return 2 * (3 - 2);
int[] max_array = new int[length];
max_array[0] = 0;
max_array[1] = 0;
max_array[2] = 1;
max_array[3] = 2;
int max = 0;
for (int i = 4; i <= length; i++)
{
max = 0;
for (int j = 1; j <= i / 2; j++)
{
int cur_value = max_array[j] * max_array[i - j];
if (cur_value > max)
{
max = cur_value;
}
}
max_array[i] = max;
}
return max;
}
//贪婪算法
public int Problem14_2(int length)
{
if (length <= 1) return 0;
if (length == 2) return 1 * (2 - 1);
if (length == 3) return 2 * (3 - 2);
int time_of_3 = length / 3;
if (length - time_of_3 * 3 == 1)
{
time_of_3 -= 1;
}
length -= time_of_3 * 3;
int time_of_2 = length / 2;
int max = (int)(Math.Pow(3, time_of_3) * Math.Pow(2, time_of_2));
return max;
}
#endregion
要点:
可以使用动态规划来解决问题的特点:
1.目标是求解最优解
2.整体问题的最优解依赖于子问题的最优解
3.可以将问题分成若干子问题且子问题之间还有重叠的部分
4.从上往下分析问题,从下往上解决问题
面试题16:数值的整数次方
public double Power(double x, int y)
{
double result = 0;
int abs_y = Math.Abs(y);
if (abs_y == 0)
{
result = 0;
return y >= 0 ? result : 1 / result;
}
if (abs_y == 1)
{
result = x;
return y >= 0 ? result : 1 / result;
}
if ((abs_y & 0x1) == 0) // %2 -> &0x1
{
result = Power(x, abs_y >> 1) * Power(x, abs_y >> 1); // /2 -> >>1
}
else
{
result = x * Power(x, (abs_y - 1) / 2) * Power(x, (abs_y - 1) / 2);
}
return y >= 0 ? result : 1 / result;
}