当前位置:   article > 正文

每次面试前必看笔试题汇总~~~~~~~~~~~~~~~~~~~~~~~~~

每次面试前必看笔试题汇总~~~~~~~~~~~~~~~~~~~~~~~~~

面试

小知识点记录: 哈希表map[j]-- 当减少到0了 不意味着j这个key对应从哈希表中删除了,只不过是value变成0了,map.count(j) 查找的j是对应 key

题目1:判断链表是否有环

#include<bits/stdc++.h>
using namespace std;

struct ListNode{
	int val;
	ListNode* next;
	ListNode():val(0),next(nullptr){}
	ListNode(int x):val(x),next(nullptr){}
}; 

//写个类
class Solution{
public:
	/*bool hasCycle(ListNode* head){
		if(head==nullptr || head->next==nullptr)
			return false;
		ListNode* slow=head;
		ListNode* fast=head->next;
		while(slow!=fast){
			if(fast==nullptr || fast->next==nullptr)
				return false;
			slow=slow->next;
			fast=fast->next->next;	
		}
		return true;		
	}
	*/
	bool hasCycle(ListNode*head){
		if(head==nullptr) return false;
		unordered_set<ListNode*> set;
		while(head){
			if(set.count(head))
				return true;
			set.insert(head);
			head=head->next;
		}
		return false;
		
	}
	
	
}; 

int main(){
	int M=5;
	ListNode* dump=new ListNode();
	ListNode* head=dump;
	for(int i=1;i<=M;i++){
		int temp;
		cin>>temp;
		head->next=new ListNode(temp);
		head=head->next;
	}
	head->next=nullptr;
	head=dump->next;
	/*Solution *p;
    cout<<p->hasCycle(head); */
    Solution p;
    cout<<p.hasCycle(head);	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

题目2:快速幂运算

class Solution {
public :
    double myPow(double x, int n) {
        if(n==0)   return 1;
        long N=n; //防止负数最大反转出错 
        if(N<0){
            x=1/x;
            N=-N;
        }
        double result=1;
        while(N>0){
            if(N%2==1)   result*=x;
            N>>=1;    
            x*=x;
        }
        return result;

    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

题目3:反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        
        ListNode* pre=nullptr;
        ListNode* curr=head;
        while(curr){
            ListNode* temp=curr->next;
            curr->next=pre;
            pre=curr;
            curr=temp;  
        }
        return pre; 
    }
};
//反转双向链表的话
public:
    ListNode* reverseList1(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            //curr->front=next; 如果是反转双向链表的话 前指针指向原来的next指针就行了
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        //pre->front=nullptr; //不用加 我就是说下。
        return prev;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

题目4 合并两个有序链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dump=new ListNode();
        ListNode* temp=dump;
        while(l1!=nullptr && l2!=nullptr){
            if(l1->val<l2->val){
                temp->next=l1;
                l1=l1->next;
                temp=temp->next;
            }
            else{
                temp->next=l2;
                l2=l2->next;
                temp=temp->next;
            }
        }
        temp->next= l1==nullptr ? l2:l1;
        return dump->next;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

题目5 合并K个升序链表

class Solution {
public:
   //合并两个有续链表~
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dump=new ListNode();
        ListNode* temp=dump;
        while(l1!=nullptr && l2!=nullptr){
            if(l1->val<l2->val){
                temp->next=l1;
                l1=l1->next;
                temp=temp->next;
            }
            else{
                temp->next=l2;
                l2=l2->next;
                temp=temp->next;
            }
        }
        temp->next= l1==nullptr ? l2:l1;
        return dump->next;
    }
    //合并K个有序链表
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (int i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;   
    } 
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

题目6 和为K的连续子数组—前缀和+哈希表

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> mp;
        mp[0] = 1;
        int count = 0, pre = 0;
        for (auto& x:nums) {
            pre += x;
            if (mp.count(pre - k)==1) {
                count += mp[pre - k];
            }
            mp[pre]++;
        }
        return count;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

连续子数组表:需要长度大于等于2,和为K的倍数

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        int m = nums.size();
        if (m < 2) {
            return false;
        }
        unordered_map<int, int> mp;
        mp[0] = -1;
        int remainder = 0;
        for (int i = 0; i < m; i++) {
            remainder = (remainder + nums[i]) % k;
            if (mp.count(remainder)) {   /如果前面的前缀和 和后面这个弄下来的余数相同,说明后面这一段 被K整除! 
                int prevIndex = mp[remainder];
                if (i - prevIndex >= 2) {
                    return true;
                }
            } else 
                mp[remainder] = i;  // key=前缀和,value=索引 注意到只有没出现才会更新下标,所以保证最左下标,所以else必不可少!!!
        }
        return false;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

题目7:数组中最小的K个数

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        vector<int> vec(k, 0);
        if (k == 0) { // 排除 0 的情况
            return vec;
        }
        priority_queue<int> Q;
        for (int i = 0; i < k; ++i) {
            Q.push(arr[i]);
        }
        for (int i = k; i < (int)arr.size(); ++i) {
            if (Q.top() > arr[i]) {
                Q.pop();
                Q.push(arr[i]);
            }
        }
        for (int i = 0; i < k; ++i) {
            vec[i] = Q.top();
            Q.pop();
        }
        return vec;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

题目8:第K个素数/质数

class Solution {
public:
    int getKthMagicNumber(int k) {
        priority_queue<long, vector<long>, greater<long>> pq;
            pq.push(1);
         long res;
         while (k > 0) {
             res = pq.top();
             pq.pop();
             while (!pq.empty() && res == pq.top())
                 pq.pop();
             pq.push(res * 3);
             pq.push(res * 5);
             pq.push(res * 7);
            k--;
         }
         return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

题目9: 1143: 最长公共子序列—动态规划

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int m = text1.length(), n = text2.length();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        for (int i = 1; i <= m; i++) {
            char c1 = text1.at(i - 1); //at返回下标为i-1 
            for (int j = 1; j <= n; j++) {
                char c2 = text2[j-1];
                if (c1 == c2) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[m][n];
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

题目10: 3. 无重复字符的最长子串 —滑动窗口

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> window;
        int left = 0, right = 0;
        int res = 0; // 记录结果
        while (right < s.size()) {
            char c = s[right];
            right++;
        // 进行窗口内数据的一系列更新
            window[c]++;
        // 判断左侧窗口是否要收缩
            while (window[c] > 1) {
                char d = s[left];
                left++;
            // 进行窗口内数据的一系列更新
                window[d]--;
            }
        // 在这里更新答案
        res = max(res, right - left);
    }
    return res;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

题目11: 三数之和—固定first 然后对second 和third 使用双指针办法

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        for (int first = 0; first <n-2; ++first) {
            // 需要和上一次枚举的数不相同 用一次就行了
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            //进入双指针环节
            int target = -nums[first];
            int second = first + 1;
            int third = n - 1;
            while(second<third) {
                if(nums[second] + nums[third]==target){
                    ans.push_back({nums[first], nums[second], nums[third]});
                    while(second<third && nums[second] == nums[++second]);//去重
                    while(second<third && nums[third] == nums[--third]);       
                }
                else if(nums[second] + nums[third] > target){
                    while(second<third && nums[third] == nums[--third]);                
                }
                else if(nums[second] + nums[third] < target){
                    while(second<third && nums[second] == nums[++second]);                 
                }                  
            }
        }
        return ans;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

题目12: 最长回文子串-------用双指针的方式 也可以用动态规划 有空看下

class Solution {
public:
    //中心扩展对称即是回文串,在这基础上用双指针
    string longestPalindrome(string s) {
        int n=s.size(); string res;
        for(int i=0;i<n;i++){
            string s1=palindrome(s,i,i);
            string s2=palindrome(s,i,i+1);
            res=res.size()>s1.size() ? res:s1;
            res=res.size()>s2.size() ? res:s2;
        }
        return res;
    }
    //调用辅助函数
    string palindrome(string & s, int l,int r){
        while(l>=0 && r<s.size() && s[l]==s[r]){
            l--;r++;
        }
        return s.substr(l+1,r-l-1);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

补充–回文子字符串的个数, 也是中心扩展

class Solution {
public:
    int countSubstrings(string s) {
        int num = 0;
        int n = s.size(); 
        for(int i=0;i<n;i++)//遍历回文中心点
        {
            for(int j=0;j<=1;j++)//j=0,中心是一个点,j=1,中心是两个点
            {
                int l = i;
                int r = i+j;
                while(l>=0 && r<n && s[l--]==s[r++])num++;
            }
        }
        return num;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

补充131:分割回文串

class Solution {
private:
    vector<vector<int>> f;
    vector<vector<string>> ret;
    vector<string> ans;
    int n;

public:
    void dfs(const string& s, int i) {
        if (i == n) {
            ret.push_back(ans);
            return;
        }
        for (int j = i; j < n; ++j) { //探索同一个i下不同的j的组合
            if (f[i][j]) {
                ans.push_back(s.substr(i, j - i + 1));
                dfs(s, j + 1); //继续探索当前i往后走的新开始
                ans.pop_back();
            }
        }
    }

    vector<vector<string>> partition(string s) {
        n = s.size();
        f.assign(n, vector<int>(n, true));

        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                f[i][j] = (s[i] == s[j]) && f[i + 1][j - 1];
            }
        }

        dfs(s, 0);
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

题目13:全排列II —包含重复元素

class Solution {
    vector<int> vis;
    vector<int>perm;
    vector<vector<int>>ans;
public:
    void backtrack(vector<int>& nums) {
        if(perm.size()==nums.size()){
            ans.emplace_back(perm);
            return;
        }
        for(int i=0; i<nums.size();i++){
            if(vis[i] ||(i>0 && nums[i]==nums[i-1] && !vis[i-1]))
                continue;
            vis[i]=1;
            perm.emplace_back(nums[i]);
            backtrack(nums);
            perm.pop_back();
            vis[i]=0;
        }      
    }
    //进入主函数
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vis.resize(nums.size());
        sort(nums.begin(),nums.end());
        backtrack(nums);//一开始肯定对第0个元素操作
        return ans;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

题目14:全排列无重复

class Solution {
    vector<int> vis;
    vector<int> track;
    vector<vector<int>> res;   
public:
    void backtrack(vector<int>  &Num) {
        if(track.size()==Num.size()){
           res.push_back(track);
           return;
        }
        for(int i=0; i<Num.size();i++){
            if(vis[i]) continue;
            vis[i]=1;
            track.push_back(Num[i]);
            backtrack(Num);
            track.pop_back();
            vis[i]=0;
        }     
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vis.resize(nums.size());
        backtrack(nums);
        return res;
    }  
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

题目15:最长公共前缀

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if (!strs.size()) {
            return "";
        }
        string prefix = strs[0];
        int count = strs.size();
        for (int i = 1; i < count; ++i) {
            prefix = longestCommonPrefix(prefix, strs[i]);
            if (!prefix.size()) //如果前缀为0,提前退出了
                break;
        }
        return prefix;
    }

    string longestCommonPrefix(const string& str1, const string& str2) {
        int length = min(str1.size(), str2.size());
        int index = 0;
        while (index < length && str1[index] == str2[index]) {
            ++index;
        }
        return str1.substr(0, index); //从0开始index个
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

题目16:两个栈实现队列

class CQueue {
    stack<int> stack1,stack2; //私有变量 也是全局把可以理解为
public:
    //三个函数 初始化、入栈和出栈
    CQueue() { //初始化清空栈
        while (!stack1.empty()) {
            stack1.pop();
        }
        while (!stack2.empty()) {
            stack2.pop();
        }
    }
    
    void appendTail(int value) {
        stack1.push(value); //入栈
    }
    
    int deleteHead() { //出栈函数
        // 如果第二个栈为空
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        } 
        if (stack2.empty()) {
            return -1;
        } else {
            int deleteItem = stack2.top();
            stack2.pop();
            return deleteItem;
        }
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

题目17: 组合总和 leetcode39—注意到这里是可以无限使用次数,而且无重复,所以每一层是新的就是选择和不选择,选择了可以继续选择

class Solution {
    vector<vector<int>> ans;
    vector<int> combine;
public:
    void dfs(vector<int>& candidates, int target, int idx) {
        if (idx == candidates.size()) { //记录枚举位置
            return;
        }
        if (target == 0) {
            ans.emplace_back(combine);
            return;
        }
        // 要么直接跳过,枚举下个
        dfs(candidates, target,idx + 1);
        // 要么选择当前数 不跳过
        //选择的时候如果这个数很大了,那就没啥路走了结束 其实就是无法选择 这个分支结束而已。
        if (target - candidates[idx] >= 0) {
            combine.emplace_back(candidates[idx]);
            dfs(candidates, target - candidates[idx],idx);
            combine.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        dfs(candidates, target, 0);
        return ans;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

优化方法:

class Solution {
    vector<vector<int>> ans;
    vector<int> combine;
public:
    void dfs(vector<int>& candidates, int target, int idx) {
        if(target<0) return;

        if (target == 0) 
        {
            ans.emplace_back(combine);
            return;
        }
        
        for (int i = idx; i < candidates.size(); i++){ //每一层可以继续选择当前元素
            target-=candidates[i];
            combine.emplace_back(candidates[i]);
            dfs(candidates, target,i);
            target+=candidates[i];
            combine.pop_back();
            
        }
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        dfs(candidates, target, 0);
        return ans;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

题目18:组合总和------这里每个数字只能使用一次,可能包含重复元素

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    vector<bool> used;

    void backtracking(vector<int>& candidates, int target,int startIndex) {
        if(target<0) return;
        
        if (target==0) {
            result.push_back(path);
            return;
        }
        //这里的for是给了他不同的起点。 就是说不走回头路,往后走
        for (int i = startIndex; i < candidates.size(); i++) {
            // used[i - 1] == true,说明同一树支candidates[i - 1]使用过
            // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            // 要对同一树层使用过的元素进行跳过
            if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {
                continue;
            }
            target -= candidates[i];
            path.push_back(candidates[i]);
            used[i] = true;
            backtracking(candidates, target,i + 1); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次
            used[i] = false;
            target += candidates[i];
            path.pop_back();
        }
    }

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        used.resize(candidates.size(),false);
        path.clear();
        result.clear();
        // 首先把给candidates排序,让其相同的元素都挨在一起。
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target,0);
        return result;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

题目19:两数之和,是无排序的。如果有序的话就是双指针

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            if (hashtable.count(target-nums[i])) 
                return {hashtable[target-nums[i]], i};
            hashtable[nums[i]] = i;
        }
        return {};
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

题目20:两数相加2222

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val: 0;
            int n2 = l2 ? l2->val: 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) {
                l1 = l1->next;
            }
            if (l2) {
                l2 = l2->next;
            }
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);
        }
        return head;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        return addTwoNumbersCore(l1, l2, 0);
    }

    ListNode* addTwoNumbersCore(ListNode* l1, ListNode* l2, int carry) {
        if (!l1 && !l2 && carry == 0) {
            // 当输入的节点均为null且无需处理进位时,结束
            return nullptr;
        }
        int val = carry + (l1 ? l1 -> val : 0) + (l2 ? l2 -> val : 0); // 计算当前的和
        ListNode* res = new ListNode(val % 10);
        res -> next = addTwoNumbersCore((l1 ? l1 -> next : nullptr), (l2 ? l2 -> next : nullptr), val / 10);
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

题目20:二叉树的最大深度

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

题目22:平衡二叉树

class Solution {
public:
    int height(TreeNode* root) {
        if (root == NULL) {
            return 0;
        } else {
            return max(height(root->left), height(root->right)) + 1;
        }
    }

    bool isBalanced(TreeNode* root) {
        if (root == NULL) {
            return true;
        } else {
            return abs(height(root->left) - height(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);
        }
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

题目23:二叉树的所有路径

class Solution {
public:
    void construct_paths(TreeNode* root, string path, vector<string>& paths) {
        if (root != nullptr) {
            path += to_string(root->val);
            if (root->left == nullptr && root->right == nullptr) {  // 当前节点是叶子节点
                paths.push_back(path);                              // 把路径加入到答案中
            } else {
                path += "->";  // 当前节点不是叶子节点,继续递归遍历
                construct_paths(root->left, path, paths);
                construct_paths(root->right, path, paths);
            }
        }
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> paths;
        construct_paths(root, "", paths);
        return paths;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

题目24:判断是否是对称的二叉树

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==nullptr) return true;
        return recur(root->left,root->right);
    }
    bool recur(TreeNode* root1, TreeNode* root2){
        if(!root1 && !root2)    return true;
        if(!root1 || !root2 ||root1->val!=root2->val)    return false;

        return recur(root1->left,root2->right) && recur(root1->right,root2->left);
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

题目25:镜像二叉树

class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }
        TreeNode* left = mirrorTree(root->left);
        TreeNode* right = mirrorTree(root->right);
        root->left = right;
        root->right = left;
        return root;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

题目26:回文数

class Solution {
public:
    bool isPalindrome(int x) {
        // 特殊情况:
        // 如上所述,当 x < 0 时,x 不是回文数。
        // 同样地,如果数字的最后一位是 0,为了使该数字为回文,
        // 则其第一位数字也应该是 0
        // 只有 0 满足这一属性
        if (x < 0 || (x % 10 == 0 && x != 0)) {
            return false;
        }

        int revertedNumber = 0;
        while (x > revertedNumber) {
            revertedNumber = revertedNumber * 10 + x % 10;
            x /= 10;
        }

        // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
        // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
        // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
        return x == revertedNumber || x == revertedNumber / 10;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
class Solution {
public:
    bool isPalindrome(int x) {
        string s=to_string(x);
        int n=s.size();
        int left=0,right=n-1;
        while(left<right){
            if(s[left]==s[right]){
                left++;right--;
            }
            else
                return false;
        }
        return true;

    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

题目27:整数反转

class Solution {
public:
    int reverse(int x) {
        long long r = 0;
        while (x) {
            r = r * 10 + x % 10;
            x /= 10;
        }
        if (abs(r) > INT_MAX) return 0;
        return r;
    }
};

```cpp
class Solution {
public:
    int reverse(int x) {
        int r = 0;
        while (x) {
            if (r > 0 && r > (INT_MAX - x % 10) / 10) return 0;
            if (r < 0 && r < (INT_MIN - x % 10) / 10) return 0;
            r = r * 10 + x % 10;
            x /= 10;
        }
        return r;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

题目28: Z字形变换

class Solution {
public:
    string convert(string s, int numRows) {
        if (numRows == 1) return s;
        vector<string> rows(min(numRows, int(s.size())));
        int curRow = 0;
        bool goingDown = false;

        for (char c : s) {
            rows[curRow] += c;
            if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
            curRow += goingDown ? 1 : -1;
        }

        string ret;
        for (string row : rows) ret += row;
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

题目29:剑指offer04:二维数组的查找~ 妙啊

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int i = matrix.size() - 1, j = 0;
        while(i >= 0 && j < matrix[0].size())
        {
            if(matrix[i][j] > target) i--;
            else if(matrix[i][j] < target) j++;
            else return true;
        }
        return false;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

题目30: 连续子数组的最大和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0, maxAns = nums[0];
        for (const auto &x: nums) {
            pre = max(pre + x, x);
            maxAns = max(maxAns, pre);
        }
        return maxAns;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

题目31:根据先序和中序构造二叉树

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    //很明显此题需要递归 
    return newtree(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
    }
    //构造调用函数
    TreeNode* newtree(vector<int>& preorder,int l1,int r1, vector<int>& inorder,int  l2,int r2){
        if(l1>r1)
        return nullptr;
        TreeNode* root=new TreeNode();
        root->val=preorder[l1];
        //要找到根节点在中序遍历中的位置
        int index=0;int length=0;
        for(int i=l2;i<=r2;i++){
           if(inorder[i]==root->val){
               index=i;
               length=index-l2;
               break;
           }
        }
        //构建左右子树
        root->left=newtree(preorder,l1+1,l1+length,inorder,l2,index-1);
        root->right=newtree(preorder,l1+length+1,r1,inorder,index+1,r2);
        return root;
    }

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

32:409 最长回文串

class Solution {
public:
    int longestPalindrome(string s) {
        unordered_map<char, int> count;
        int ans = 0;
        for (char c : s)
            ++count[c];
        for (auto p : count) {
            int v = p.second;
            ans += v / 2 * 2;
            if (v % 2 == 1 and ans % 2 == 0)
                ++ans;
        }
        return ans;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

33:翻转字符串里的单词

利用 stringstream 把字符串s 转化为输入流 此时我们自定义的ssin就可以向cin一样去使用
我们自定义的ssin和cin一样, 每次读取时都会跳过空格

class Solution {
public:
    string reverseWords(string s) {
        string s1[1000], s2;
        int i = 0;
        stringstream ssin(s);
        while(ssin>>s1[i])
            i++;
        for(int j = i - 1; j > 0; j--)
            s2+=s1[j]+" ";
        s2+=s1[0];

        return s2;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

189.旋转数组–补充题----给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> newArr(n);
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i]; //比如数组有8位,这个8就放到开头的地方~
        }
        nums.assign(newArr.begin(), newArr.end());//容器赋值运算,将new中的值送给nums
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

方法2,用o(1)的空间复杂度
https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode-solution-nipk/

class Solution {
public:
    void reverse(vector<int>& nums, int start, int end) {
        while (start < end) {
            swap(nums[start], nums[end]);
            start += 1;
            end -= 1;
        }
    }

    void rotate(vector<int>& nums, int k) {
        k %= nums.size();
        reverse(nums, 0, nums.size() - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.size() - 1);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

路经总和II–输出二叉树路径中等于target的路径

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;

    void dfs(TreeNode* root, int targetSum) {
        if (root == nullptr) {
            return;
        }
        path.emplace_back(root->val);
        targetSum -= root->val;
        if (root->left == nullptr && root->right == nullptr && targetSum == 0) {
            ret.emplace_back(path);
        }
        dfs(root->left, targetSum);
        dfs(root->right, targetSum);
        path.pop_back();
    }

    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        dfs(root, targetSum);
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

路经总和I–判断是否存在这样的路

class Solution {
public:
    bool hasPathSum(TreeNode *root, int sum) {
        if (root == nullptr) {
            return false;
        }
        if (root->left == nullptr && root->right == nullptr) {
            return sum == root->val;
        }
        return hasPathSum(root->left, sum - root->val) ||
               hasPathSum(root->right, sum - root->val);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

队列的解:

class Solution {
public:
    bool hasPathSum(TreeNode *root, int sum) {
        if (root == nullptr) {
            return false;
        }
        queue<TreeNode *> que_node;
        queue<int> que_val;
        que_node.push(root);
        que_val.push(root->val);
        while (!que_node.empty()) {
            TreeNode *now = que_node.front();
            int temp = que_val.front();
            que_node.pop();
            que_val.pop();
            if (now->left == nullptr && now->right == nullptr) {
                if (temp == sum) {
                    return true;
                }
                continue;
            }
            if (now->left != nullptr) {
                que_node.push(now->left);
                que_val.push(now->left->val + temp);
            }
            if (now->right != nullptr) {
                que_node.push(now->right);
                que_val.push(now->right->val + temp);
            }
        }
        return false;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

剑指 Offer II 080. 含有 k 个元素的组合–给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。

class Solution {
private:
    void helper(int i, int n, int k, vector<vector<int>>& ret, vector<int>& cur) {
        if (cur.size() == k) {
            ret.emplace_back(cur);
            return;
        }
        // i 超界
        if (i > n) {
            return;
        }
        
        //  不加入 i
        helper(i + 1, n, k, ret, cur);

        // 加入 i
        cur.push_back(i);
        helper(i + 1, n, k, ret, cur);
        cur.pop_back();
    }

public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ret;
        vector<int> cur;
        helper(1, n, k, ret, cur);
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

环形链表的入口-- 开头到环形入口走a步,环长度b,慢指针走=nb,快走2nb,慢指针到入口要走a+nb,所以还需要走a,那就快指针到头开始走

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
        while (true) {
            if (fast == nullptr || fast->next == nullptr) return nullptr;
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) break;
        }
        fast = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/788804
推荐阅读
相关标签
  

闽ICP备14008679号