【算法题】牛客研发最爱考[61 - 70]

链表中倒数第k个节点(快慢指针)

处理特殊情况:k大于链表数量,return {}

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
    
    
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    ListNode* FindKthToTail(ListNode* pHead, int k) {
    
    
        // write code here
        auto p = pHead, q = pHead;
        while(k && p != NULL) p = p->next,k --;
        if(k > 0) return NULL;  // k大于链表数量,return {}
        while(p != NULL)
        {
    
    
            p = p->next;
            q = q->next;
        }
        
        return q;
    }
};

矩阵元素查找(二分)

类似二分的思想,从右上角开始枚举,每次干掉一行或者一列

class Solution {
    
    
public:
    vector<int> findElement(vector<vector<int> > mat, int n, int m, int x) {
    
    
        // write code here
        int i  =0, j = m - 1;
        while(i < n && j >= 0)
        {
    
    
            if(mat[i][j] == x) return {
    
    i,j};
            else if(mat[i][j] > x) j --;
            else if(mat[i][j] < x) i ++ ;
        }
        return {
    
    };
    }
};

最小编辑代价(DP)

72. 编辑距离进阶版

class Solution {
    
    
public:
    /**
     * min edit cost
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @param ic int整型 insert cost
     * @param dc int整型 delete cost
     * @param rc int整型 replace cost
     * @return int整型
     */
    int minEditCost(string str1, string str2, int ic, int dc, int rc) {
    
    
        // write code here
        int n = str1.size(), m = str2.size();
        vector<vector<int>> f(n + 1,vector<int>(m + 1));
        
        // 从A 变成 B 的代价
        for(int i = 0;i <= n;i ++ ) f[i][0] = dc* i;
        for(int i = 0;i <= m;i ++ ) f[0][i] = ic * i;
        
        for(int i = 1;i <= n;i ++ )
            for(int j = 1;j <= m;j ++ )
            {
    
    
                f[i][j] = min(f[i - 1][j] + dc,f[i][j - 1] + ic);
                if(str1[i - 1] != str2[j - 1]) f[i][j] = min(f[i][j],f[i - 1][j - 1] + rc);
                else f[i][j] = min(f[i][j],f[i - 1][j - 1]);
            }
        return f[n][m];
    }
};

82. 删除排序链表中的重复元素 II(递推)

(线性扫描) O(n)
为了方便处理边界情况,我们定义一个虚拟元素 dummy 指向链表头节点。
然后从前往后扫描整个链表,每次扫描元素相同的一段,如果这段中的元素个数多于1个,则将整段元素直接删除。
时间复杂度分析:整个链表只扫描一遍,所以时间复杂度是 O(n)。

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
    
    
public:
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        // write code here
        ListNode* dummy = new ListNode(-1);
        dummy->next = head; // 头结点可能会变,增加虚拟头结点
        
        auto p = dummy ;
        while(p->next)
        {
    
    
            auto q = p->next;
            while(q && q->val == p->next->val) q = q->next;
            if(p->next->next == q) p = p->next;
            else p->next = q;
        }
        return dummy->next;
    }
};

二叉树的最大路径和(递归)

/**
 * 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 ans = INT_MIN;
    int maxPathSum(TreeNode* root) {
    
    
        dfs(root);
        return ans;
    }

    // 返回从root向下走的最大值
    int dfs(TreeNode* root)
    {
    
    
        if(!root) return 0;

        auto left = dfs(root->left);
        auto right = dfs(root->right);

        ans = max(ans,left + root->val + right); // 枚举最高点,任何路径都有最高点
        return max(0,root->val + max(left,right));
    }
};

链表的奇偶重排(递推)

四个指针剥离原链表

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
    
    
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* oddEvenList(ListNode* head) {
    
    
        // write code here
        if(head == NULL || head->next == NULL) return head;
        
        auto odd_head = head,even_head = head->next, odd = head,even = head->next;
        for(ListNode *p = head->next->next; p ;)
        {
    
    
            odd->next = p, odd = p, p = p->next;
            if(p)
            {
    
    
                even->next = p,even = p, p = p->next;
            }
        }
        odd->next = even_head,even->next = NULL;
        return odd_head;
    }
};

求路径(DP)

class Solution {
    
    
public:
    /**
     * 
     * @param m int整型 
     * @param n int整型 
     * @return int整型
     */
    int uniquePaths(int m, int n) {
    
    
        // write code here
        vector<vector<int>> f(m + 1,vector<int>(n + 1));
        f[1][1] = 1;
        for(int i = 1;i <= m;i ++ )
           for(int j = 1;j <= n;j ++ )
                f[i][j] += f[i - 1][j] + f[i][j -1];
       
        
        return f[m][n];
    }
};

将字符串转化为整数(模拟)

注意int溢出处理

class Solution {
    
    
public:
    int atoi(const char *str) {
    
    
        if(*str=='\0') return 0;
        
        const char* p =str;
        while(*p==' ') ++p; // 去除空格
        
        int sign=1;
        if(*p == '-') sign = -1,p ++ ;
        else if(*p == '+') p ++ ;

        //long res=0;
        int res = 0;
        while(*p >= '0' && *p <= '9'){
    
    
            //res = res * 10 + *p - '0';
            int x = *p - '0';
            // 判断溢出
            if(sign > 0 && res > (INT_MAX - x) / 10) return INT_MAX;
            if(sign < 0 && -res < (INT_MIN + x) / 10) return INT_MIN;
            if(-res * 10 - x == INT_MIN) return INT_MIN;
            res = res * 10 + x;
            p ++ ;
        }
        return res*sign;
    }
};

数字字符串转化为IP地址(爆搜)

题解

class Solution {
    
    
public:
    /**
     * 
     * @param s string字符串 
     * @return string字符串vector
     */
    vector<string> ans;
    vector<string> restoreIpAddresses(string s) {
    
    
        // write code here
        dfs(s,0,0,"");
        return ans;
    }
    
        // k表示截断的IP地址个数
    void dfs(string &s,int u,int k,string path)
    {
    
    
        if(u == s.size())
        {
    
    
            if(k == 4){
    
    
                path.pop_back(); // 去除最后一个'.';
                ans.push_back(path);
            }
            return;
        }
        if(k == 4) return; // 剪枝
        
        for(int i = u ,t = 0;i < s.size();i ++ )
        {
    
    
            if(i > u && s[u] == '0') break; // 有前导0
            t = t * 10 + s[i] - '0';
            if(t <= 255) dfs(s,i + 1,k + 1,path + to_string(t) + '.');
            else break;
        }
    }
};

反转数字

C++里 负数取模为负数


class Solution {
    
    
public:
    int reverse(int x) {
    
    
        int res = 0; // 
        while(x){
    
    
            int t = x % 10; // C++里 负数取模为负数
            if(x > 0 && res > (INT_MAX - t) / 10) return 0; // 溢出判断
            if(x < 0 && res < (INT_MIN - t) / 10) return 0;
            res = res * 10 + t;  // res * 10 + t > INT_MAX 
                                // res * 10 + t < INT_MIN
            x /= 10;
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43154149/article/details/114269557
70