手撕代码+++!!!

手撕

  • 数组
    • 1. 两数之和
    • 2. 第k大
    • 3. 出现次数topk
    • 4. 合并两有序数组
    • 5. 移除元素
    • 6. 数组的交集
    • 7. 旋转数组的最小数字
    • 8.变态跳台阶
    • 9. 二进制1的个数
    • 10. 三数之和为0
    • 11. 前K大
  • 链表
    • 1. 反转链表
    • 2. 删除倒数第k个结点
    • 3. 合并两个有序链表
    • 4. 旋转链表
    • 5. 移除链表元素
  • 字符串
    • 1. 有效括号
    • 2. 字符串相加
    • 3.只反转单词
    • 4. 倒置字符串
    • 5.替换空格
    • 6. 最长不重复子串
  • 二叉树
    • 1. 二叉树的中序遍历
    • 2. 平衡二叉树
    • 3. 重建二叉树
  • 两个栈实现队列

数组

1. 两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //建立一个unordred_map,key是nums[i],value 是i
        //遍历表,找到target-nums[i],并且不是自身。
        unordered_map<int,int> hashtable;
        for(int i = 0; i < nums.size(); i++)
        {
            hashtable[nums[i]] = i;
        }
        for(int i = 0; i < nums.size(); i++)
        {
            if(hashtable.find(target-nums[i]) != hashtable.end() && hashtable[target - nums[i]] != i)
            {
                return {i, hashtable[target - nums[i]]};
            }
        }
        return {};

    }
};

2. 第k大

class Finder {
public:
    int findKth(vector<int> a, int n, int K) {
        // write code here
        //快排+二分,递归调用
        QuickSort(a, n , K , 0, n-1);
    }
    
    int QuickSort(vector<int>& a, int n, int K, int start, int end)
    {
        int base = a[start];
        int i = start;
        int j = end;
        int res = 0; 
        while(i < j)
        {
            while(i < j && a[j] >= base)
            {
                j--;
            }
            while(i < j && a[i] <= base)
            {
                i++;
            }
            if(i < j)
            {
                swap(a[i],a[j]);
            }
        }
        swap(a[start],a[j]);
        
        if(n - j == K) {return a[j];}
        
        else if(n - j > K) {res=  QuickSort(a,n,K,j + 1, end);}
        else if(n - j < K) {res =  QuickSort(a,n,K,start,j-1);}
        return res;
    }
};

int main()
{
	int a[5] = { 1,2,7,8,5 };
	int k = 3;
	quickFindMaxK(a, 0, 4, k);
	for (int i = 0; i < k; i++)
		cout << a[i] << " ";
	cout << endl;

}

3. 出现次数topk

:建立一个小顶堆,然后遍历「出现次数数组」:
如果堆的元素个数小于 kk,就可以直接插入堆中。
如果堆的元素个数等于 kk,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 kk 个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中。
遍历完成后,堆中的元素就代表了「出现次数数组」中前 kk 大的值


class Solution {
public:
    static bool cmp(pair<int, int>& m, pair<int, int>& n) {
        return m.second > n.second;
    }

    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> occurrences;
        for (auto& v : nums) {
            occurrences[v]++;
        }

        // pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
        for (auto& [num, count] : occurrences) {
            if (q.size() == k) {
                if (q.top().second < count) {
                    q.pop();
                    q.emplace(num, count);
                }
            } else {
                q.emplace(num, count);
            }
        }
        vector<int> ret;
        while (!q.empty()) {
            ret.emplace_back(q.top().first);
            q.pop();
        }
        return ret;
    }
};

4. 合并两有序数组

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        //1. 扩大数组为m+n,指针p从后往前遍历
        //2. 分别从后往前遍历俩数组,大的替换p
        //3. 循环条件,p>= 0;
        int p = m + n -1;
        int p1 = m -1;
        int p2 = n -1;
        while(p >= 0)
        {
            if(p1 < 0)
            {
                nums1[p] = nums2[p2];
                p2--;
            }
            else if(p2 <0)
            {
                nums1[p] == nums1[p1];
                p1--;
            }
            else if(nums1[p1] <= nums2[p2])
            {
                nums1[p] = nums2[p2];
                p2--;
            }
            else
            {
                nums1[p] = nums1[p1];
                p1--;
            }
            p--;
        }
    }
};

5. 移除元素

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if(nums.size()==0)
        {
            return 0;
        }
        int right = nums.size() - 1;
        for(int i = 0; i <= right; i++)
        {
            while(right >= 0 && nums[right] == val)
            {
                right--;
            }
            if(nums[i] == val && i < right)
            {
                nums[i] = nums[right];
                nums[right] = val;
            }
           
        }
        return right + 1;
    }
};

6. 数组的交集

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        map <int,int> m;
        vector<int> v;
        for(auto e : nums2)
        {
            m[e]++;
        }

       
        for(auto e : nums1)
        {
            if(m[e] > 0)
            {
                m[e] = 0;
                v.push_back(e);
            }
        }
        return v;

    }
};

7. 旋转数组的最小数字

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size() == 0)
        {
            return 0;
        }
        int first = 0, last = rotateArray.size() - 1;
        
        while(first < last)
        {
            int mid = first + ((last - first)>>1);
            if(rotateArray[first] < rotateArray[last])
            {
                return rotateArray[first];
            }
            else{
                if(rotateArray[mid] > rotateArray[last])
                {
                    first = mid + 1;
                }else{
                    if(rotateArray[mid] <= rotateArray[last])
                    {
                        last = mid;
                    }
                    
                }
            }
        }
        return rotateArray[first];
    }
};

8.变态跳台阶

class Solution {
public:
    int jumpFloorII(int number) {
        if(number == 0 || number == 1) return number;
        int a = 1,b;
        for(int i = 2;i <= number; i++)
        {
            b = a << 1;
            a = b;
        }
        return b;

    }
};

9. 二进制1的个数

class Solution {
public:
     int  NumberOf1(int n) {
         int count = 0;
         while(n!= 0)
         {
             count++;
             n = n & (n-1);
         }
         return count;
         
     }
     
};

10. 三数之和为0


#include
#include
#include
 
using namespace std;
 
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) 
	{
		vector<int> tmp(3);
		vector<vector<int> > rs;
		sort(num.begin(), num.end());
 
		for (int i = 0; i < num.size(); i++)
		{
			for (int j = i+1, k = num.size()-1; j < k; )
			{
				if (num[i]+num[j]+num[k] < 0) j++;
				else if (num[i]+num[j]+num[k] >0) k--;
				else
				{
					tmp[0] = num[i]; 
					tmp[1] = num[j]; 
					tmp[2] = num[k];
					rs.push_back(tmp);
					j++, k--;
					while (j<k && num[j] == num[j-1]) j++;
					while (j<k && num[k] == num[k+1]) k--;
				}
			}
			while (i<num.size() && num[i] == num[i+1]) i++;
		}
		return rs;
	}
	
int main() 
{
	vector<vector<int> > vt;
	int a[] = {-2,13,-5,-4,-7,8,0,-9,6,7,0,-4,2,1,-2,4};
	int len = sizeof(a)/sizeof(int);
	vector<int> t(a, a+len);
	Solution solu;
	vt = solu.threeSum(t);
	for (auto x:vt)
	{
		cout<<"(";
		for (auto y:x)
			cout<<y<<"\t";
		cout<<")"<<endl;
	}
	cout<<endl;
 
	system("pause");
	return 0;
}

11. 前K大

#include
#include
#define N 100010
using namespace std;
 
 
 
void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
 
void quicksort(int a[], int s, int e, int k)
{
	// s 是数组的开始,e是数组的最后一个元素,k要求的前k个最大值
	int m = a[s];
	if (s >= e)
		return;
	int i = s, j = e;
	while (i != j)
	{
		while (j > i&&a[j] >= m)
		{
			j--;
		}
		swap(a[i], a[j]);
		while (j > i&&a[i] <= m)
		{
			i++;
		}
		swap(a[i], a[j]);
	}
	//quicksort(a, s, i - 1);
	//quicksort(a, i + 1, e);
	if ((e - j) == k)
	{
		// 如果已经有k个数在key的右边,则目标完成
		return;
	}
	else if ((e - j) > k)
	{
		// 对右边的从j到e的数进行操作
		quicksort(a, j, e, k);
	}
	else
	{
		// 对从s到j的数
		quicksort(a, s, j, e - j - k);
	}
 
}
 
int main()
{
	int n, k;
	int a[N];
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
		scanf("%d", &a[i]);
	scanf("%d", &k);
	quicksort(a, 0, n - 1, k);
	sort(a+n-k, a + n);
	for (int i = n-1; i >= n-k; i--)
	{
		printf("%d\n", a[i]);
	}
	return 0;
}

链表

1. 反转链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *cur = NULL;
        ListNode *pre = head;

        while(pre != NULL)
        {
            ListNode *t = pre -> next;
            pre -> next = cur;
            cur = pre;
            pre = t;
        }
        return cur;

    }
};

2. 删除倒数第k个结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //新建一个前继结点;
        //快指针先走n步,再同时走,直到末尾-》next不为空,可以定位到删除元素的前一个结点
        ListNode*  dummy = new ListNode(0);
        dummy -> next = head;
        ListNode* fast = dummy, *slow = dummy;
        while(n--)
        {
            if(fast!= nullptr)
            {
                fast = fast -> next;
            }
            
        }
        while(fast->next != nullptr)
        {
            fast = fast -> next;
            slow = slow -> next;
        }
        slow -> next = slow -> next -> next;
        return dummy-> next;

    }
};

3. 合并两个有序链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        //迭代方式;
        //1. 新建一个链表头,初始化一个哨兵结点。
        //2. 循环条件:两个链表都不为空; 比较两个链表结点大小,将小的结点链接在新节点后。
        //3. 当一个链表为空时,将剩余链表结点链接。
        ListNode* head = new ListNode(-1);
        ListNode* prev = head;
        while(l1 != nullptr && l2 != nullptr)
        {
            if(l1 -> val <= l2 -> val)
            {
                prev -> next = l1;
                l1 = l1 -> next;
            }
            else
            {
                prev -> next = l2;
                l2  = l2 -> next;
            }
            prev = prev-> next;
        }
        if(l1 == nullptr) prev -> next = l2;
        else if(l2 == nullptr) prev -> next = l1;
        return head -> next;
    }
};

4. 旋转链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head == NULL) {return NULL;}
        ListNode* left = head, *right = head;
        int n = 0;
        ListNode* p = head;
        while(p)
        {
            p = p -> next;
            n++;
        }
        k %= n;
        while(k--)
        {
            if(right != NULL)
            {
                right = right -> next;
            }
            
        }
        while(right->next != NULL)
        {
            right = right -> next;
            left = left -> next;
        }
        right -> next = head;
        head = left -> next;
        left -> next = NULL;
        return head;
        
    }
};

5. 移除链表元素

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode *dummy = new ListNode(0);
        dummy->next = head;
        ListNode *pre = dummy, *cur = head;

        while(cur != NULL)
        {
            if(cur -> val == val)
            {
                pre -> next = cur -> next;
                cur = cur -> next;
            }else
            {
                cur = cur -> next;
                pre = pre -> next;
            }
        }
        return dummy -> next;
    }
};

字符串

1. 有效括号

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for(int i = 0; i < s.size(); i++)
        {
            switch(s[i])
            {
                case '(':
                    st.push('(');
                    break;
                case '[':
                    st.push('[');
                    break;
                case '{':
                    st.push('{');
                    break;
                case ')':
                    if(st.empty()) return false;
                    else if(st.top() == '(')
                    {
                        st.pop();
                    }
                    else{return false;}
                    break;
                case ']':
                    if(st.empty()) return false;
                    else if(st.top() == '[')
                    {
                        st.pop();
                    }
                    else{return false;}
                    break;
                case '}':
                    if(st.empty()) return false;
                    else if(st.top() == '{')
                    {
                        st.pop();
                    }
                    else{return false;}
                    break;
            }
        }
        if(st.empty()) return true;
        else return false;

    }
};

2. 字符串相加

class Solution {
public:
    string addStrings(string num1, string num2) {
        int str1 = num1.size() -1;
        int str2 = num2.size() -1;
        string ans;
        int result = 0, add = 0;
        int x = 0, y = 0;
        while(str1 >= 0 || str2 >= 0 || add != 0)
        {
            if(str1 >= 0)
            {
                x = num1[str1] - '0';
            }
            else{
                x = 0;
            }
            if(str2 >= 0)
            {
                y = num2[str2] - '0';
            }
            else{
                y = 0;
            }
            result = x + y + add;
            ans.push_back('0' + result % 10);
            add = result / 10;
            str1--;
            str2--;
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

3.只反转单词

class Solution {
public:
    string reverseWords(string s) {
        if(s.size() == 0)
        {
            return s;
        }
        int n = s.size();
        int front = 0; int back = 0;
        for(int i = 0; i < n - 1; i++)
        {
            if(s[back] != ' ')
            {
                back++;
            }
            else
            {
                reverse(s.begin() + front, s.begin() + back);
                front = back + 1;
                back = front;
            }
        }
        back++;
        reverse(s.begin() + front, s.begin() + back);
        return s;

    }
};

4. 倒置字符串

#include
#include
#include
using namespace std;

int main()
{
    string s;
    getline(cin,s);
    
    reverse(s.begin(),s.end());
    int len = s.size();
    int front = 0, back = 0;
    for(int i =0; i < len - 1; i++)
    {
        if(s[i] != ' ')
        {
            back++;
        }
        else{
            reverse(s.begin()+front,s.begin()+back);
            front = back + 1;
            back = front;
        }
       
    }
     back++;
     reverse(s.begin()+front,s.begin()+back);
    cout<<s<<endl;
    return 0;
}

5.替换空格

class Solution {
public:
	void replaceSpace(char *str,int length) {
        if(str == nullptr || length < 0)
        {
            return;
        }
        int count = 0;
        for(int i = 0; i < length; i++)
        {
            if(str[i] == ' ')
            {
                count++;
            }
        }
        if(count == 0)
        {
            return;
        }
        int new_length = length + count*2;
        for(int i = length; i >= 0; i--)
        {
            if(str[i] != ' ')
            {
                str[new_length] = str[i];
                new_length--;
            }else{
                str[new_length--] = '0';
                str[new_length--] = '2';
                str[new_length--] = '%';
            }
         
        }
    }
};

6. 最长不重复子串

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
       //滑动窗口思想
       //哈希表存放字符出现的次数,
       //左右双指针,右指针增加找到符合不重复字符的窗口,左指针增加改变窗口大小来回
       //循环条件:出现重复元素
       unordered_map<char,int> window;
       int left = 0, right = 0;
       int res = 0;
       int n = s.size();
       while(right < n)
       {
           char c1 = s[right];
           window[c1]++;
           right++;
           while(window[c1] > 1)
           {
               char c2 = s[left];
               window[c2]--;
               left++;
           }
           res = max(res,right - left);
       }
       
       return res;

    }
};

二叉树

1. 二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> v;
        TreeNode* rt = root;
        while(rt || s.size())
        {
            while(rt)
            {
                s.push(rt);
                rt = rt -> left;
            }
            rt = s.top();
            s.pop();
            v.push_back(rt -> val);
            rt = rt -> right;
        }
        return v;
        
    }
};

2. 平衡二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int height(TreeNode* root)
    {
        if(root == NULL)
        {
            return 0;
        }
        else 
            return max(height(root -> right), height(root -> left)) + 1;
    }
    bool isBalanced(TreeNode* root) {
        if(root == NULL)
        {
            return true;
        }
        else
        {
            return abs(height(root -> right) - height(root -> left)) <= 1 && isBalanced(root -> left) && isBalanced(root -> right);
        } 
    }
};

3. 重建二叉树

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size() == 0 || vin.size() == 0)
        {
            return NULL;
        }
        TreeNode* head = new TreeNode(pre[0]);
        vector<int> pre_left, pre_right, vin_left, vin_right;
        int vinlen = vin.size();
        int temp = 0;
        for(int i = 0;i < vinlen; i++)
        {
            if(vin[i] == pre[0])
            {
                temp = i;
                break;
            }
        }
        for(int i = 0; i < temp ; i++)
        {
            pre_left.push_back(pre[i+1]);
            vin_left.push_back(vin[i]);
        }
        for(int i = temp+1; i < vinlen; i++)
        {
            pre_right.push_back(pre[i]);
            vin_right.push_back(vin[i]);
        }
        head ->left = reConstructBinaryTree(pre_left, vin_left);
        head ->right = reConstructBinaryTree(pre_right, vin_right);
        return head;

    }
};

两个栈实现队列

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
        
    }

    int pop() {
        if(stack2.empty())
        {
            while(!stack1.empty())
            {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int ret = stack2.top();
        stack2.pop();
        return ret;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

你可能感兴趣的:(刷题,链表,二叉树)