【Notes14】剑指offer_21-30题


21.调整数组顺序使奇数位于偶数前面

在这里插入图片描述

//java版
class Solution {
    
    
    public int[] exchange(int[] nums) {
    
    
        int left = 0;
        int right = nums.length - 1;
        while(left < right)
        {
    
    
            //从左往右找偶数 找到偶数 停止
            while(left < right && nums[left] % 2 == 1) left ++;
            //从右往左找奇数 找到奇数停止
            while(left < right && nums[right] % 2 == 0) right --;
            if(left < right)
            {
    
    
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
            }
        }
        return nums;
    }
}
//C++版
class Solution {
    
    
public:
    void reOrderArray(vector<int> &array) {
    
    
        /*
        queue<int> q1, q2;
        
        for(int i = 0; i < array.size(); i ++)
        {
            if(array[i] % 2 == 1)
                q1.push(array[i]);
            else
                q2.push(array[i]);
        }
        
        array.clear();
        while(q1.size())
        {
            array.push_back(q1.front());
            q1.pop();
        }
        while(q2.size())
        {
            array.push_back(q2.front());
            q2.pop();
        }
        */
        
        //排序前后的稳定性
        //是不是奇数
        //前面偶数 后面奇数  交换
        for(int i = 0; i < array.size(); i ++)
        {
    
    
            for(int j = array.size() - 1; j > i; j --)
            {
    
    
                if(array[j] % 2 == 1 && array[j - 1] % 2 == 0)
                    swap(array[j],array[j - 1]);
            }
        }
        
    }
};

22.链表中倒数第k个节点

在这里插入图片描述

//java版
class Solution {
    
    
    public ListNode getKthFromEnd(ListNode head, int k) {
    
    
        //单个指针 走到头  len 
        //从头走 len - k
        
        //双指针
        ListNode first = head;
        ListNode second = head;
        for(int i = 0; i < k; i ++)
        {
    
    
            //k 大于链表长度
            if(first == null) return null;
            first = first.next;
        }
        while(first != null)
        {
    
    
            first = first.next;
            second = second.next;
        }
        return second;
    }
}
//C++版
class Solution {
    
    
public:
    ListNode* FindKthToTail(ListNode* head, unsigned int k) {
    
    
        int n = 0;
        for(ListNode* p = head; p; p = p -> next) n ++;
        
        if(k > n) return nullptr;
        ListNode* p = head;
        for(int i = 0; i < n - k; i ++) p = p -> next;
        
        return p;
    }
};

23.链表中环的入口结点

在这里插入图片描述

//java版
class Solution {
    
    
    public ListNode entryNodeOfLoop(ListNode head) {
    
    
        /*
        //hash表 从头到尾遍历  
        Set<ListNode> hash = new HashSet<>();
        
        while(head != null)
        {
            if(!hash.add(head))
                return head;
            head = head.next;
        }
        
        return null;
        */
        //快慢指针
        ListNode slow = head;//走一步
        ListNode fast = head;//走两步
        while(fast != null)
        {
    
    
            slow = slow.next;
            fast = fast.next.next;
            if(fast == slow)
            {
    
    
                slow = head;
                while(slow != fast)
                {
    
    
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
            
        }
        
        return null;
    }
}
//C++版
class Solution {
    
    
public:
    ListNode* EntryNodeOfLoop(ListNode* head)
    {
    
    
        /*
        //快慢指针
        auto fast = head, slow = head;
        while(fast && slow)
        {
            fast = fast -> next;
            slow = slow -> next;
            if(fast) fast = fast -> next;
            else break;
            //相遇点
            if(fast == slow)
            {
                slow = head;
                while(fast != slow)
                {
                    fast = fast -> next;
                    slow = slow -> next;
                }
                return slow;
            }
        }
        return 0;
        */
        //hash表
        unordered_map<ListNode*,int> h;
        int id = 1;
        for(auto i = head; i ; i = i -> next, id ++)
        {
    
    
            if(h[i] != 0)
            {
    
    
                return i;
            }
            else
                h[i]  = id;
        }
        
        return NULL;
    }
};

24.反转链表

在这里插入图片描述

//java版
class Solution {
    
    
    public ListNode reverseList(ListNode head) {
    
    
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null)
        {
    
    
            //让cur指向 pre
            //然后 pre  cur 都往后走一个
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}
//C++版
class Solution {
    
    
public:
    ListNode* ReverseList(ListNode* pHead) {
    
    
        //找到前驱结点
        ListNode* pre = nullptr;
        
        auto cur = pHead;
        while(cur)
        {
    
    
            auto next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

25.合并两个排序的链表

在这里插入图片描述

//java版
class Solution {
    
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    
    
        //归并排序思想
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        while(l1 != null && l2 != null)
        {
    
    
            if(l1.val <= l2.val)
            {
    
    
                cur.next = l1;
                l1 = l1.next;
                cur = cur.next;
            }
            else
            {
    
    
                cur.next = l2;
                l2 = l2.next;
                cur = cur.next;
            }
        }
        if(l1 != null)
        {
    
    
            cur.next = l1;
        }
        if(l2 != null)
        {
    
    
            cur.next = l2;
        }
        return dummy.next;
    }
}
//C++版
class Solution {
    
    
public:
    ListNode* Merge(ListNode* p1, ListNode* p2)
    {
    
    
        //归并思想
        ListNode* dummy = new ListNode(-1);
        auto cur = dummy;
        while(p1 && p2)
        {
    
    
            if(p1 -> val <= p2 -> val)
            {
    
    
                cur -> next = p1;
                cur = cur -> next;
                p1 = p1 -> next;
            }
            else{
    
    
                cur -> next = p2;
                cur = cur -> next;
                p2 = p2 -> next;
            }
        }
        
        if(p1) cur -> next = p1;
        else cur -> next = p2;

        return dummy -> next;
    }

26.树的子结构

在这里插入图片描述

//java版
class Solution {
    
    
    public boolean isSubStructure(TreeNode A, TreeNode B) {
    
    
        //递归
        //A根 B根
        //A左子树 B
        //A右子树 B
        if(A == null  || B == null) return false;
        return (issubtree(A, B) || isSubStructure(A.left, B)|| isSubStructure(A.right, B));
    }
    public boolean issubtree(TreeNode A, TreeNode B) {
    
    
        //true 
        if(B == null) return true;
        //false 
        if(A == null || A.val != B.val) return false;
        return issubtree(A.left, B.left) && issubtree(A.right, B.right);
    }
}
//C++版
class Solution {
    
    
public:
    bool HasSubtree(TreeNode* t1, TreeNode* t2)
    {
    
    
        if(!t1 || !t2) return false;
        if(isPart(t1, t2)) return true;
        
        return HasSubtree(t1 -> left, t2) || HasSubtree(t1 -> right, t2);
    }
    
    //只能比较t1  t2各自为根结点的树
    bool isPart(TreeNode* t1, TreeNode* t2)
    {
    
    
        if(!t2) return true;//t2已经遍历到了叶节点结束
        if(!t1 || t1 -> val != t2 -> val) return false;
        //比较左右子孩子
        return isPart(t1 -> left, t2 -> left) && isPart(t1 -> right, t2 -> right);
    }
};

27.二叉树的镜像

在这里插入图片描述

//java版
class Solution {
    
    
    public TreeNode mirrorTree(TreeNode root) {
    
    
        //左右子树交换
        if(root == null) return null;
        TreeNode temp = root.left;
        root.left = mirrorTree(root.right);
        root.right = mirrorTree(temp);
        return root;
    }
}
//C++版
class Solution {
    
    
public:
    void Mirror(TreeNode *root) {
    
    
        if(!root) return;
        
        Mirror(root -> left);
        Mirror(root -> right);
        //交换左右结点
        swap(root -> left, root -> right);
    }
};

28.对称的二叉树

在这里插入图片描述

//java版
class Solution {
    
    
    public boolean isSymmetric(TreeNode root) {
    
    
        if(root == null) return true;
        return dfs(root.left, root.right);
    }
    public boolean dfs(TreeNode left, TreeNode right)
    {
    
    
        if(left == null && right == null) return true;
        if(left == null || right ==  null || left.val != right.val) return false;
        return dfs(left.left, right.right) && dfs(left.right, right.left);
    }
}
//C++版
class Solution {
    
    
public:
    bool isSymmetrical(TreeNode* root)
    {
    
    
        if(!root) return true;
        
        return dfs(root -> left, root -> right);
    }
    
    bool dfs(TreeNode* t1, TreeNode* t2)
    {
    
    
        if(!t1 || !t2) return !t1 && !t2;
        if(t1 -> val != t2 -> val) return false;
        
        return dfs(t1 -> left, t2 -> right) && dfs(t1 -> right, t2 -> left);
    }
};

29.顺时针打印矩阵

在这里插入图片描述

扫描二维码关注公众号,回复: 12557801 查看本文章
//java版
class Solution {
    
    
    public int[] spiralOrder(int[][] matrix) {
    
    
        //判断边界 
        if(matrix.length == 0)
            return new int[0];
        //右下左上
        int left = 0, right = matrix[0].length -1, up = 0, down = matrix.length - 1;
        int num = 0;
        int[] res = new int[(right + 1) * (down + 1)];
        while(true)
        {
    
    
            //右
            for(int i = left; i <= right; i ++)
                res[num ++] = matrix[up][i];
            if(++ up > down) break;
            //下
            for(int i = up; i <= down; i ++)
                res[num ++] = matrix[i][right];
            if(-- right < left ) break;
            //左
            for(int i = right; i >= left; i --)
                res[num ++] = matrix[down][i];
            if(-- down < up) break; 
            //上
            for(int i = down; i >= up; i --)
                res[num ++] = matrix[i][left];
            
            if(++ left > right) break;
        }
        return res;
    }
}
//C++版
class Solution {
    
    
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
    
    
        vector<int> res;
        //定义方向
        //碰壁换方向  右下左上
        
        if(matrix.empty()) return res;
        
        int n = matrix.size(), m = matrix[0].size();
        vector<vector<bool>> state(n, vector<bool>(m, false));
        int dx[4] = {
    
    -1, 0, 1, 0}, dy[4] = {
    
    0, 1, 0, -1};
        int x = 0, y = 0, d = 1;
        
        for(int i = 0; i < n * m; i ++)
        {
    
    
            res.push_back(matrix[x][y]);
            state[x][y] = true;
            
            int a = x + dx[d], b = y + dy[d];
            if(a < 0 || a >= n || b < 0 || b >= m || state[a][b] == true)   
            {
    
    
                d = (d + 1) % 4;
                a = x + dx[d], b = y + dy[d];
            }
            
            x = a, y = b;
        }
        
        return res;
    }
};

30.包含min函数的栈

在这里插入图片描述

//java版
class MinStack {
    
    
    Stack<Integer> A, B;//A正常的栈  B记录最小元素的栈
    /** initialize your data structure here. */
    public MinStack() {
    
    
        A = new Stack<>();
        B = new Stack<>();
    }
    
    public void push(int x) {
    
    
        //判断当前元素 和栈内最小的元素 对比
        A.add(x);
        if(B.empty() || B.peek() >= x)
            B.add(x);
    }
    
    public void pop() {
    
    
        //栈顶元素 是不是 最小的
        //if(A.pop().equals(B.peek()))
        //    B.pop();
        if(A.peek().equals(B.peek()))//不能用 == 必须用 equals
            B.pop();
        
        A.pop();
    }
    
    public int top() {
    
    
        //直接写
        return A.peek();
    }
    
    public int min() {
    
    
        //找到栈内最小的元素 直接写
        return B.peek();
    }
}
//C++版
class Solution {
    
    
public:
    stack<int> stk, min_stk;
    
    void push(int value) {
    
    
        stk.push(value);
        if(min_stk.empty() || min_stk.top() >= value) min_stk.push(value);
    }
    void pop() {
    
    
        if(min_stk.top() == stk.top()) min_stk.pop();
        
        stk.pop();
    }
    int top() {
    
    
        return stk.top();
    }
    int min() {
    
    
        return min_stk.top();
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43435675/article/details/107235682