面试题03. 数组中重复的数字
int findRepeatNumber(int* nums, int numsSize){
int temp;
for(int i=0; i<numsSize; i++){
while (nums[i] != i){
if(nums[i] == nums[nums[i]]){
return nums[i];
}
temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
return -1;
}
如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回ture.
相当于先将数组当前位置值处的值与当前位置比较,若相等则不管,若不等,则比较当前位置值与当前位置值处的值,若相等则说明必然重复,若不相等则交换这两个数,然后就不断重复,多次交换后将数组按序号排序,i处的值为i,出现重复则完成。
面试题04. 二维数组中的查找
bool findNumberIn2DArray(int** matrix, int matrixSize, int* matrixColSize, int target){
if (NULL == matrix || 0 == matrixSize || NULL == matrixColSize || 0 == *matrixColSize)
return false;
int flag = matrix[matrixSize-1][0];
//printf("%d\n", flag);
int j = 0, i = matrixSize-1;
while(i >=0 && j < *matrixColSize){
if(flag == target){
return true;
}
else if(flag < target){
j++;
if(j<*matrixColSize){
flag = matrix[i][j];
}
//printf("2222i = %d,j = %d %d\n", i, j, flag);
}
else{
i--;
if(i >= 0){
flag = matrix[i][j];
}
//printf("33333i = %d,j = %d %d\n", i, j, flag);
}
}
return false;
}
从左下角或右下角开始判断(大于和小于区分行和列):
若将 matrix 中的左下角元素(标志数)记作tmp ,则有:
若 tmp > target ,则 target 一定在 flag 所在行的上方,即tmp所在行可被消去。
若 tmp < target ,则 target 一定在 flag 所在列的右方,即tmp所在列可被消去。
面试题05. 替换空格
char* replaceSpace(char* s){
int len = strlen(s);
for(int i=0; i<len; i++){
if(s[i] == ' '){
s[i] = '%';
s = (char* )realloc(s, sizeof(char) * (len + 3));//注意此处要多一位放‘\0’
s[len + 2] = '\0';
len += 2;
for(int j=len-1; j>i+2; j--){
s[j] = s[j-2];
}
s[i+1] = '2';
s[i+2] = '0';
i += 2;
}
}
return s;
}
char* replaceSpace(char* s){
int len=strlen(s);
int blankcnt=0;
for(int i=0;i<len;++i)
if(s[i]==' ')
blankcnt++;//统计出有多少个空格
int newlen=2*blankcnt+len;
int oldlen=len;
s=(char *)realloc(s,sizeof(char)*(newlen+1));
s[newlen]='\0';
newlen--;
oldlen--;
while(oldlen>=0&&newlen!=oldlen) {
if(s[oldlen]==' ') {
s[newlen--]='0';
s[newlen--]='2';
s[newlen--]='%';
}
else
s[newlen--]=s[oldlen];
oldlen--;
}
return s;
}
这里先统计空格数,直接增加足够的数组长度,然后从后到前整个复制,用两指针oldlen和newlen改变数组的位置,从而将原数组复制改变。
面试题06. 从尾到头打印链表
int* reversePrint(struct ListNode* head, int* returnSize){
struct ListNode *p = head;
int len = 0;
while(p != NULL){
len++;
p = p->next;
}
*returnSize = len;
int *res = (int *)malloc(sizeof(int)*(10001));
struct ListNode *q = head;
int i = len-1;
while(q != NULL){
res[i] = q->val;
q = q->next;
i--;
}
return res;
}
法二:栈
class Solution {
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode temp = head;
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] print = new int[size];
for (int i = 0; i < size; i++) {
print[i] = stack.pop().val;
}
return print;
}
}
面试题07. 重建二叉树
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
if(preorderSize == 0 || inorderSize == 0){
return NULL;
}
struct TreeNode *T;
int tmp = preorder[0];
int i=0;
for(i=0; i<inorderSize; i++){
if(inorder[i] == tmp){
struct TreeNode *p;
p = (struct TreeNode *)malloc(sizeof(struct TreeNode));
p->val = inorder[i];
p->left = NULL;
p->right = NULL;
T = p;
break;
}
}
int *lp = (int *)malloc(sizeof(int)*preorderSize), *li = (int *)malloc(sizeof(int)*preorderSize), *rp = (int *)malloc(sizeof(int)*preorderSize), *ri = (int *)malloc(sizeof(int)*preorderSize);
int kp=0, ki = 0, t = 0;
for(int j=0; j<i; j++){
li[kp] = inorder[j];
kp++;
}
for(int j=1; j<=i; j++){
lp[ki] = preorder[j];
ki++;
}
for(int j=i+1; j<inorderSize; j++){
rp[t] = preorder[j];
ri[t] = inorder[j];
t++;
}
if(kp != 0){
T->left = buildTree(lp, kp, li, ki);
}
if(t != 0)
T->right = buildTree(rp, t, ri, t);
struct TreeNode *q = T;
while(q != NULL){
q = q->left;
}
return T;
}
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
//空数组返回空指针,表示空树
if(preorderSize==0) return NULL;
int all,num=preorderSize;//标记先序数组第一个元素在中序数组位置
struct TreeNode* node=malloc(sizeof(struct TreeNode));
node->val=preorder[0];
//匹配preorder[0]在inorder的下标
while(num--) if(inorder[num]==preorder[0]) break;
all=num+1;
node->left=buildTree(preorder+1,num,inorder,num);
node->right=buildTree(preorder+all,preorderSize-all,inorder+all,inorderSize-all);
return node;
}
//借鉴代码,此处直接利用指针而不是复制到新数组,节省时间和空间
也可以利用栈先保存遍历结果,使用迭代将数据连接成树
使用前序遍历的第一个元素创建根节点。
创建一个栈,将根节点压入栈内。
初始化中序遍历下标为 0。
遍历前序遍历的每个元素,判断其上一个元素(即栈顶元素)是否等于中序遍历下标指向的元素。
若上一个元素不等于中序遍历下标指向的元素,则将当前元素作为其上一个元素的左子节点,并将当前元素压入栈内。
若上一个元素等于中序遍历下标指向的元素,则从栈内弹出一个元素,同时令中序遍历下标指向下一个元素,之后继续判断栈顶元素是否等于中序遍历下标指向的元素,若相等则重复该操作,直至栈为空或者元素不相等。然后令当前元素为最后一个想等元素的右节点。
遍历结束,返回根节点。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
TreeNode root = new TreeNode(preorder[0]);
int length = preorder.length;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
int inorderIndex = 0;
for (int i = 1; i < length; i++) {
int preorderVal = preorder[i];
TreeNode node = stack.peek();
if (node.val != inorder[inorderIndex]) {
node.left = new TreeNode(preorderVal);
stack.push(node.left);
} else {
while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
node = stack.pop();
inorderIndex++;
}
node.right = new TreeNode(preorderVal);
stack.push(node.right);
}
}
return root;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/mian-shi-ti-07-zhong-jian-er-cha-shu-by-leetcode-s/
面试题10- II. 青蛙跳台阶问题
设跳上 n 级台阶有 f(n) 种跳法。在所有跳法中,青蛙的最后一步只有两种情况: 跳上 1 级或 2 级台阶。
当为 1 级台阶: 剩 n−1 个台阶,此情况共有 f(n−1) 种跳法;
当为 2 级台阶: 剩 n−2 个台阶,此情况共有 f(n−2) 种跳法。
使用数组存储各级台阶的跳法,则f(n)=f(n-1)+f(n-2)
class Solution(object):
def numWays(self, n):
"""
:type n: int
:rtype: int
"""
a = np.zeros(n+1, dtype = int)
print a
a[0] = 1
a[1] = 1
a[2] = 2
for i in range(3, n):
a[i] = a[i-1] + a[i-2]
for i in range(0, n):
print a[i]
return a[n]
改进,使用a,b两个数字交替代替数组
class Solution:
def numWays(self, n: int) -> int:
a, b = 1, 1
for _ in range(n):
a, b = b, a + b
return a % 1000000007
作者:jyd
链接:https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/solution/mian-shi-ti-10-ii-qing-wa-tiao-tai-jie-wen-ti-dong/