Week 13. 第283-300题

283. 移动零

分析

双指针算法

如果x不是0, 就放到当前位置上, 当前位置++
扫描一遍完后, 将后面的所有数字置0

code

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int k = 0;
        for (auto& x : nums) 
            if (x) nums[k ++ ] = x;
        while (k < nums.size()) nums[k ++ ] = 0;
        
    }
};

284. 顶端迭代器

分析

增加一个额外的缓存, 来放置当前的数

如果是peek操作, 就将缓存中的元素输出
next将缓存的元素输出, 同时将后面的元素移到缓存上
hasNext
在这里插入图片描述

code

/*
 * Below is the interface for Iterator, which is already defined for you.
 * **DO NOT** modify the interface for Iterator.
 *
 *  class Iterator {
 *		struct Data;
 * 		Data* data;
 *  public:
 *		Iterator(const vector<int>& nums);
 * 		Iterator(const Iterator& iter);
 *
 * 		// Returns the next element in the iteration.
 *		int next();
 *
 *		// Returns true if the iteration has more elements.
 *		bool hasNext() const;
 *	};
 */

class PeekingIterator : public Iterator {
public:
    int cur;
    bool has_next;
	PeekingIterator(const vector<int>& nums) : Iterator(nums) {
	    // Initialize any member here.
	    // **DO NOT** save a copy of nums and manipulate it directly.
	    // You should only use the Iterator interface methods.
	    has_next = Iterator::hasNext();
        if (has_next) cur = Iterator::next();
	}
	
    // Returns the next element in the iteration without advancing the iterator.
	int peek() {
        return cur;
	}
	
	// hasNext() and next() should behave the same as in the Iterator interface.
	// Override them if needed.
	int next() {
	    int t = cur;
        // 将下一个元素放到展台上
        has_next = Iterator::hasNext();
        if (has_next) cur = Iterator::next();

        return t;
	}
	
	bool hasNext() const {
	    return has_next;
	}
};

287. 寻找重复数

分析

转化成找环的入口的问题

0的位置上是1
0->1
1的位置上是3
1->3
2的位置上是4
2->4
3的位置上是2
3->2
4的位置上是2
4->2

在这里插入图片描述

联动

leetcode 142 环的入口

code

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int a = 0, b = 0;
        while (true) {
            a = nums[a];
            b = nums[nums[b]];

            if (a == b) {
                a = 0;
                while (a != b) {
                    a = nums[a];
                    b = nums[b];
                }
                return a;
            }
        }
        return -1;
    }
};

289. 生命游戏

分析

模拟题

code

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) {
        if (board.empty() || board[0].empty()) return ;
        int n = board.size(), m = board[0].size();
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ ){
                int live = 0;
                for (int x = max(0, i - 1);  x <= min(n - 1, i + 1); x ++ )
                    for (int y = max(0, j - 1); y <= min(m - 1, j + 1); y ++ )
                        if ((x != i || y != j) && (board[x][y] & 1))  // 不包括自己x != i || y != j
                            live ++;
                
                int cur = board[i][j] & 1, next;
                if (cur == 1) {
                    if (live < 2 || live > 3) next = 0;
                    else next = 1;
                }else {
                    if (live == 3) next = 1;
                    else next = 0;
                }
                board[i][j] |= next << 1;
            }

        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ )
                board[i][j] >>= 1;
    }
};

290. 单词规律

分析

判断映射, 和单射就可以了

code

class Solution {
public:
    bool wordPattern(string pattern, string str) {
        vector<string> words;
        stringstream ssin(str);
        string word;
        while (ssin >> word) words.push_back(word);
        if (pattern.size() != words.size()) return false;

        unordered_map<char, string> pw;
        unordered_map<string, char> wp;

        for (int i = 0; i < pattern.size(); i ++ ) {
            auto a = pattern[i];
            auto b = words[i];

            if (pw.count(a) && pw[a] != b) return false;
            pw[a] = b;
            if (wp.count(b) && wp[b] != a) return false;
            wp[b] = a;
        }
        return true;
    }
};

292. Nim 游戏

分析

当前是0颗石子的话, 必输
当前是1颗石子的话, 那我们只需要拿1颗石子, 那么对手必输, 我们必胜
1, 2, 3 全拿走就可以了
4的话, 拿1颗石子, 变成3, 3的话对手必胜, 我们必输
拿2颗石子, 也是输, 拿1颗石子也是输
因此4颗石子的话, 我们先手, 无论怎么拿也是输

如果是5的话, 我们拿1颗石子, 对手就会进入4, 那么对手必输
同样的道理, 6, 7都是必胜, 因为可以转化到4, 令对手必输

8的话必输

找下规律, 可以发现 n % 4 == 0的话, 必输
n % 4 != 0的话, 必胜

在这里插入图片描述

如果n % 4 != 0的话, 第1次拿 n % 4就可以了, 拿完石子个数就变成n % 4 == 0, 是4的倍数, 然后不管对手拿多少(设对手拿了x), 我们都拿 4 - x

如果上来就是 n % 4 == 0的话, 不管我们拿多少, 对手可以拿 4 - x, 所以我们必输

code

class Solution {
public:
    bool canWinNim(int n) {
        return n % 4;
    }
};

295. 数据流的中位数

分析

维护一个对顶堆, 保证下面比上面的数多1个

如果整个数列个数是奇数, 返回下面的堆顶
如果是偶数, 那么返回两个堆顶的平均值

插入:
如果 t <= x, 那么将t放到下面
否则; 表示t在右半边, 将t放到上面
插完之后, 上下元素个数不满足要求了; 比如下面比上面元素多2个, 那么需要将下面这个堆的堆顶放到上面

同理上面的多的话, 需要将上面的堆顶移动到下面堆

所以插入操作只需要常数次的操作O(logn)

查询操作是O(1)的

code

class MedianFinder {
public:
    priority_queue<int, vector<int>, greater<int>> up;
    priority_queue<int> down;
    /** initialize your data structure here. */
    MedianFinder() {

    }
    
    void addNum(int num) {
        if (down.empty() || down.top() >= num) {
            down.push(num);
            if (down.size() > up.size() + 1) {
                up.push(down.top()); down.pop();
            }
        }else {
            up.push(num);
            if (up.size() > down.size()){
                down.push(up.top()); up.pop();
            }
        }
    }
    
    double findMedian() {
        if ((down.size() + up.size()) % 2) return down.top();
        else return (down.top() + up.top()) / 2.0;
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

297. 二叉树的序列化与反序列化

分析

基于dfs的先序遍历
在这里插入图片描述

code

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    string path;
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        dfs_s(root);
        return path;
    }

    void dfs_s(TreeNode* root){
        if (!root) path += "#,";
        else {
            path += to_string(root->val) + ',';
            dfs_s(root->left);
            dfs_s(root->right);
        }
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int u = 0;
        return dfs_d(data, u);
    }

    TreeNode* dfs_d(string& data, int& u) {
        if (data[u] == '#') {
            u += 2; // 当前是空, 需要跳过两个字符, 一个#, 一个,
            return NULL;
        }else {
            int k = u;
            while (data[u] != ',') u ++ ;
            auto root = new TreeNode(stoi(data.substr(k, u - k)));
            u ++ ; // 跳过逗号
            root->left = dfs_d(data, u);
            root->right = dfs_d(data, u);
            return root;
        }
    }
};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

299. 猜数字游戏

分析

hash表存一下次数就可以了
tot表示总的在两个字符串出现过的次数
buills表示对应位置 相同的次数

code

class Solution {
public:
    string getHint(string secret, string guess) {
        unordered_map<char, int> hash;
        for (auto c : secret) hash[c] ++ ;
        int tot = 0;
        for (auto c : guess)
            if (hash[c] > 0) {
                tot ++ ;
                hash[c] -- ;
            }

        int bulls = 0;
        for (int i = 0; i < secret.size(); i ++ )
            if (secret[i] == guess[i])
                bulls ++ ;

        return to_string(bulls) + "A" + to_string(tot - bulls) + "B";

    }
};

300. 最长递增子序列

分析(nlogn)

求一下以每个数结尾的最长上升子序列

找到最大的一个长度, 使得在这个长度下, 结尾的最大值<a[i]

最大的长度+1, 就是以a[i]结尾的最大长度

code

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> q;
        for (auto x : nums) {
            if (q.empty() || x > q.back()) q.push_back(x);
            else {
                if (x <= q[0]) q[0] = x;
                else {
                    int l = 0, r = q.size() - 1;
                    while (l < r) {
                        int mid = l + r + 1 >> 1;
                        if (q[mid] < x) l = mid;
                        else r = mid - 1;
                    }
                    q[r + 1] = x;
                }
            }
        }
        return q.size();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园失物招领系统管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、论坛管理、公告信息管理、失物招领管理、失物认领管理、寻物启示管理、寻物认领管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 校园失物招领系统管理系统可以提高校园失物招领系统信息管理问的解决效率,优化校园失物招领系统信息处理流程,保证校园失物招领系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 ,管理员权限操作的功能包括管理公告,管理校园失物招领系统信息,包括失物招领管理,培训管理,寻物启事管理,薪资管理等,可以管理公告。 失物招领管理界面,管理员在失物招领管理界面中可以对界面中显示,可以对失物招领信息的失物招领状态进行查看,可以添加新的失物招领信息等。寻物启事管理界面,管理员在寻物启事管理界面中查看寻物启事种类信息,寻物启事描述信息,新增寻物启事信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值