[leetcode]数组总结

算法与数据结构精要
本文深入探讨了一维数组操作、加油站问题、长连续序列查找、股票投资策略、旋转数组搜索及二维数组处理等核心算法与数据结构问题,提供了解决方案及优化策略。

一维数组

1. 找递增或递减序列

while(end<n && ratings[end]>ratings[end-1])
{
    candies[end] = candies[end-1] + 1;
    end++;
}


2. 加油站问题Gas Station

n个加油站,组成一圈,每个点有加油g[i],每两个点之间耗油c[i]。

判断能不能从一个点出发绕一圈?只要g[i]之和大于等于c[i]之和即可。

找到一个合理的起点。计算v[i] = g[i]-c[i]。从某一点出发向前走,记录当前经过的v[i]和,如果大于0,则继续向前,如果小于0,则将出发点后移。直到绕成一圈。


3. 在一个数组中找出最长的连续序列(即数组中的多个元素构成序列,序列中元素值是连续的)Longest Consecutive Sequence

对于当前的元素x,分别寻找x-1,x-2...在不在数组中,直到找到某个值不在数组中为止。同理,寻找x+1,x+2...在不在数组中,直到找到某个值不在数组中为止。在找到这些值的同时可以将它们从数组中删除,避免下次重复寻找这些数组的左右连续数值。

在数组中寻找某个值的方式,如果使用hash(在C++中是unordered_set),那么每次寻找的时间代价为O(1)。


4. 给定一个start单词和一个end单词,还有一个词典。求一个从start到end的变换,变换的每一步只能改变单词中的一个字母,同时保证中间单词都在词典中。Word Ladder

宽度优先遍历。给定一个当前的单词,枚举它的每一位,枚举每一位可能的变换(25种),将变换得到的新词放到宽度优先的队列中。在队列中用” “分割每一层的单词。变化的次数实际上就是当前所在的层数。


5. 买股票问题,利益最大化。Best Time to Buy and Sell Stock I II III

1) 如果只能买一次,卖一次,怎么选择。

对于第i天,计算从第i天到第n-1天中价格最高的那天的价格highest[i],这个计算是O(n)的。

然后依次计算highest[i]-prices[i]的最大值。

2) 如果可以买卖任意多次。

找全部递增序列,在每个起始点买入,每个结束点卖出。

3) 如果只能买卖两次。

递归的方法:枚举分界的那一天k,计算第1到k天买卖一次的最大收益,和第k+1到n天买卖一次的最大收益。求得两次收益和最大的那一分界天。会超时。

动态规划的方法:计算left[i]表示第1到第i天买卖一次的最大收益,right[i]表示第i天到第n天买卖一次的最大收益。求得left[i]+right[i]最大的那一个。


6. Search in Rotated Sorted Array I II

二分的方式查找。

通过比较a[mid]与a[left],a[right]的值,可以确定左半边和右半边一个有序,一个无序。


二维数组(矩阵)

1. Surrounded Regions

从二维数组的最外面一层的每个单元开始,先判断位置是否出界,如果出界则结束标记直接返回。如果没出界,则先判断当前单元的值,如果不是O则结束标记直接返回。如果满足条件则将其标记为N,再递归的判断其相邻的(最多)四个结点的值。

递归函数为:dfs

void dfs(vector<vector<char>> &board, int h, int w)
{
        int height = board.size();
        int width = board[0].size();

        // if out of range, return
        if(h<0 || h>=height || w<0 || w>=width)
            return;
        // if the region is not 'o', return
        if(board[h][w] != 'O')
            return;
        
        // mark the original region 'O' to 'N'
        board[h][w] = 'N';
        
        // dfs, mark surrounding regions recursively
        dfs(board, h-1, w);
        dfs(board, h+1, w);
        dfs(board, h, w-1);
        dfs(board, h, w+1);
}

2. Word Search

在矩阵中枚举单词的起始位置,调用递归函数。

递归函数的参数有单词的下表begin,在矩阵中的位置[i,j],这次枚举的visited矩阵(记录每个单元是否被访问过)。

如果begin等于n,说明已经找到单词。

如果begin不等于n,如果矩阵位置出界则返回false。如果当前位置被访问过或者当前位置的字母与单词中的字母不同,则返回false。

否则将当前位置标记成visited。然后递归的调用四个方向的递归函数,如果其中任意一个返回false,则当前函数返回false。

如果没有一个方向成功的,则当前位置被置为unvisited,代表不能选择当前位置,相当于回溯!然后返回false。

这样可以保证当前visited中为true的,就是当前这次查找中被访问过的、部分匹配了的单元。

    bool find(vector<vector<char>> &board, int i, int j, string word, int begin, bool **visited)
    {
        int n = word.length();
        int height = board.size();
        int width = board[0].size();
      
        // find!
        if(begin == n)
            return true;
        
        // out of matrix
        if(i >= height || i < 0)
            return false;
        if(j >= width || j < 0)
            return false;
            
        // has been visited already or not match    
        if(visited[i][j] == true || word[begin] != board[i][j])
            return false;

        // visit this cell
        visited[i][j] = true;
            
        // visit its neighbors recursively
        if(find(board, i-1, j, word, begin+1, visited) || find(board, i+1, j, word, begin+1, visited) || find(board, i, j-1, word, begin+1, visited) || find(board, i, j+1, word, begin+1, visited))
            return true;
        
        // cancel visit this cell!!
        visited[i][j] = false;
        
        return false;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值