剑指offer刷题

面试题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/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值