算法与数据结构

链表

单链表的反转:
q = head ;
p = null;
r = head.next;
while(q ){
q.next = p;
p = q;
q = r;
r = r.next;  
}


单链表的两两互换
p = null; 
q = head;
r = head.next;
while(q && r){
p.next = r;
q. next = r.next;
r.next = q;        
p = q;
q = q.next;
r = q.next;
}


判断一个链表是否有环:
1. 遍历链表看是否能遍历到null;
2. 遍历链表,一个节点是否出现多次;
3. 快慢指针:
 fast = head;
 slow = head;
while(fast && slow){
  fast = fast.next.next;
  slow = slow.next;
  if(slow == fast){
     return ture;
  }
}
return false;



字符串正确判断
int function( a[ ]){
char stack [ ] = { };
int flag = -1, i = 0;
while(a[i]){
    if(a[i] == "{" || a[i] == "(" || a[i] == "["){
        stack[++flag]=a[i];
    }
    else if(flag < 0){
        return flase;
    }
    else if(a[i] = stack[flag]+1|| a[i] == stack[flag] +2) {
        stack[flag--] = 0;
    }
    else 
        return false;
    i++;
}
return ture;
}

利用栈实现队列的机制
stack stack1,stack2;
stack1.push(数据流输入);
stack2.push(stack1.pop);
stack2.pop;

判断数据流(str)中第k大元素
1. 建立k大的数组,排序。
2. 优先队列(建立大小为k的小堆)
int heap[ k];
while(str[i]){
if( heap.length < k){
    heap.push(str[i]);
}
if(str[i] >heap.top){
    heap.pop;
    heap.push(str[i]);
}
i++
}
return heap;

返回大小为k的滑动窗口的最大值
int function(*str,k){
    if(! str){
        return flase;
    }
    int a[],b[],j= 0,m;
    for (int i=0,l=0; i < str.length; i ++ ){
        if(i - k >= 0){
            b[m++] = str[a[j]];
        }
        if(i >= k && a[j] <= i - k){    
    a[j++] =0;
        }
        while(str[i] > str[a[j]] && l >0 ){
    a[j++] = 0;
         }
        a[l++] = i;
    }
    return b[];
}

list map 和 set : map和set一般用于计数和查询

判断两字符串是否为异位字符串
1. 将两字符串排序后,判断两字符串是否大小相等。
2. 哈希表:map计数

int function(*str,*str1){
    int map[26] = {0};
    while(str){
        map[ *str - 'a'] += 1;
        str++;
    }
    while(str1){
        map[ *str1 - 'a' ] -= 1;
        str1++;
    }
    while(map){
         if(*map != 0){
    return flase;
         }
     }
  return ture;  


两数相加
1. 双for暴力解法 时间复杂度为n的平方
2. set查询

三个数相加
1. 三for暴力解法
2. set查询
3. 先排序,后for循环找一个数,然后两指针分别指向头和尾

2:
int threeSum(*nums){
    if (len(nums) < 3){
        return error;
    }
    res = set( );
    for(int i = 0 , v = 0; i< length.nums - 2; i ++){
        int b[10];
        v = nums[i];
        for(int x = 0, j =i + 1; j < length.nums - 1; j++){
    if(b[x] != 1){
        b[-v-x] = 1;
                }
    else{
        res.add((v , -v-x . x));
    }
         }
    }
}


判断一棵树是否为二叉搜索树
1. 中序遍历,判断当前节点值是否大于上一节点值。
2. 递归

1:int isvalidBST(*root){
          int * p = null;
          return helper(root);
     }
     
     int helper(* root){
          if(root == null){
                return true;
           }
           helper(root.left);
           if(p && p. val > root.val){
                  return false;
           }
           p = root;
           return helper(root.right);
     }


2: int isvalidBST(root,min,max){
        if(root == null){
             return true;
        }
        if(min != 0 && root.val <= min){
              return false;
        }
        if(max != 0 && root.val >= max){
              return false;
        }
        return isvalidBST(root.left, root.val,0) && isvalidBST(root.right,0,root.val);
    }


最近的公共祖先
1. 寻找路径(记下路径找到公共节点)
2. 递归

2:int lowestCA(*root,treeNode p, treeNode q){
          if(root == null || root == p || root == q){
                 return root;
          }
          right = lowest(root.right , p ,q);
          left = lowest(root.left, p, q);
          if(right != null && left != null){
    return root;
          }
          else if(left != null ){
    return left;
          }
          else(right != null){
    return right;
          }
          if(right == null && left == null){
    return null;
          }
      }


递归
递归一般用于解决子问题不冲突的问题,子问题冲突则一般用动态规划

求x的n次方
1. 暴力法
2. 分治法
 int pow(x,n){
     if(n== 0){
           return 1;
     }
     if( n % 2){
           return x * pow(x, n -1);
     }
     if( n < 0){
           return pow(1/x , -n);
     }
     if(n % 2 == 0 ){
          return pow(x*x , n/2);
     }
}


求众数(出现次数大于n/2的数)
1. 暴力法 双循环O(n*n)
2. map:{x,countx} O(N)
3. sort 下标为n/2的必定是众数 快排O(nlogn)
4. 分治 把数组分两边,分别找左边的众数和右边的众数
5. 投票算法 

4: int fz(*nums,int start,int end){
            if(start == end){
                  return nums[start];
            }
            right = (nums,n/2 +1 , n);
            left = (nums, 0 , n/2);
            if(right == left){
                 return left;
            }else
    return max(count(left),count(right));

      }

贪心算法
子问题的最优解能推到最终问题的最优解(金额问题,面值互相为整数倍)
动态规划会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能

深度优先搜索(DFS)
用递归写(栈)
   
int dfs(*root){
    if(!root){
         return false;
    }
    array[i++] = root.val;
    if(root.left != null){
        dfs(root.left);
    }
    if(root.right != null){
        dfs(root.right);
    }
}

广度优先搜索(BFS)
用队列写(队列)
一层一层递进
 
int bfs(start,end){
    queue = [ ] ;
    queue.push( start);
    visited.add(start);
    int depth = 0;
    while (queue){
          depth++;
          for(int n = length(queue), i = 0; i < n; i++){
              node = queue.pop;
              visited.add(node);
              if(node.right != null && node.right not in visited){     //树不需要考虑这种情况
        queue.push(node.right);
              }
              if(node.left != null && node.left not in visited){     //树不需要考虑这种情况
        queue.push(node.left);
              }
          }  
     }
}    

二叉树的最大和最小深度 
1. bfs
2. dfs
3. 递归


1:int mindepth(*root){
          queue = [ ];
          queue.push(root);
          int level = 0; 
          while(queue){
               level ++; 
               for(int i = 0, j = length.queue; i < j;i++){
                          node = queue.pop;
                          if(!node.right && !node.left){
                                return level;
                          }
                          if(node.right){
                                 queue.push(node.right);
                          }
                          if(node.left){
                                 queue.push(node,left);
                           }
                }
          }          
     }


3: int depthmax(*root){
         if(root == null){
              return 0;
         }
         return max(depthmax(root.left),depthmax(root.right)) + 1; 
    }

    int depthmin(*root){
         if(root == null){
                return 0;
         }
         left = depthmin(root.left);
         right = depthmin(root.right);
        return min(left ,right)+1;
   }


生成有效括号组合
递归(分治)
char sckh(n){
    char a [maxsize];
    a= scyxkh(0 , 0 , n,"");
    return a;
}
scyxkh(left,right,n,result){
    if(left == n && right == n){
        return result; 
    }
    if(left < n ){
        return scyxkh(left +1 , right , n ,result + "(");
    }
    if( right < n && right < left){
        return scyxkh(left, right +1 , n , result + ")");
    }

}   


N皇后问题
DFS递归


    solveNQueen( int n){
         if( n < 1){
             return false;
         } 
         int lie = set(); 
         int pie =set(); 
         int na = set();
         nqueen(0, n , lie );
    }


    int nqueen(int row , int n, int *result){
        if(row == n){
              return result;
         }
       
         for (int i= 0; i < n ; i ++){
               if(i not in lie && (row - i) not in na && (row + i) not in pie ){
                       lie.append(i);
                       pie.append(row + i);
                       na.append(row - i);
                       nqunne(row+1,n, lie);
                       lie.remove(i);
                       pie.remove(row + i);
                       na.remove(row - i);
              }
          }
 
    }


数独:
dfs递归
加速方法①对数独中要填的空进行排序预处理
②优先可选择少的空


int board[9][9]={};
int sd(board){
    for(int i = 0; i < 9 ; i ++){
        for(int j = 0; j < 9; j++){
              if( board[i][j] == " "){
                     for(k= 1;  k < 10 ; k++){
                           if(available(i , j , k)){
                                 board[i][j] = k;
                                 if(sd(board)){
                                       return true;
                                 }
                                 else board[i][j] = " ";
                           }
                     }
                     return false;
              }
              return true;
         }
     }
}


available( int i, int j, int k){
    for(int l = 1; l < 10 ; l++){
         if(board[i][l] == k){
              return false;
         }
         if(board[l][j] == k ){
               return false;
         }
         if(board[ (i/3) *3 + l %3 ][(j /3) *3 + l %3 ] == k ){
              return false;
         }
    }
    return true;
}

二分查找法:
    int function(n , left , right){
        while(right  > = left){
              int mid = (left + right)/2;
              if(a[mid ]== n){
                    return true;
              }
              if( a[mid] > n){
                    right = mid -1;
              }
              if( a[mid] < n){
                     left = mid +1;
              }
         }
         return false;
    }


求为1的位数
1. if (x & 1== 1){ 
          count ++;
   }
   x= x >>1;
2.  x = x & (x -1)  //每次将最后一位1打掉
 while(x ! = 0){
      count ++;
      x = x & (x -1);
 }  

判断一个数是否为2的幂次方
1. 不断mod 2 
   function(int n){
        while( n != 2){
            if( n % 2 == 1){
                   return false;
             }
             n= n /2;   
        }
        return true;
   }
2. 位运算
  funtion(int n){
      if(n & (n -1) == 0 && n != 0){
    return true;
      }
      return false;
  }


把0 到 n的二进制数1的个数存进数组
1. 数出每个二进制数位为1的个数
 int *function(int n){
     int count[MAX]={};
     for(int i = 1;i < =n ; i++){
          int  j = 0;
          while(i){
               i = i&(i -1);
               j++;
         }
         count[i] = j;
     }
     return count;
 }


2. 利用前面结果,位运算做下标
 int *function(int n){
     int count[MAX]= {};
     for(int i =1; i< = n; i++){
         count[i] += count[i &(i -1)] + 1;
     }
     return count;
 }


位运算解决N皇后问题
void DFS(int row,int col,int pie,int na){
    if(row >= N){ // 递归终止条件
        count++;
        return;
    }
    int bits = (~(col | pie | na)) & ( (1 << n) -1 ); // 得到空位
    while(bits > 0){ //bits不为空
        int P = bits & -bits;//得到最后一位“1”
        DFS(row+1,col | P, (pie | P) << 1, (na | P) >> 1); //下层递归
        bits &= bits -1; //删去最后一位“1”
    }
}

动态规划
爬楼梯
1. 回溯得出递推公式
2. 列出状态方程
3.dp

int function(int n){
    if(n == 0 || n == 1 || n == 2){
        return n;
    }
    int f[N] = {1,2};
    for(int i = 2; i< n; i++){
        f[i] = f[i-1] + f[i-2];
    }
    return f[n-1];
}


三角形最小路径和
① DFS
② 贪心(不可行)
③ DP


③:int function(int *board,m,n){
          int mini[N]={0};
          for(int i = 0; i < n;  i++){
                mini[i] = board[m][i];
          }
          for(int j = m-1 ;  j>= 0 ; j--){
                for(int k = 0; k <sizeof(board[j][]); k++){
                      mini[k] = board[j][k] + min(mini[k],mini[k+1]);
                }
          }
          return mimi[0];
       }


乘积最大子序列
①递归 
②DP

②:1.列出状态方程
2. 递推公式
int function( int * nums){
    if(!nums){
        return 0;
    }
    int dp[sizeof(nums)][2] = {1,1};
    int res = 0;
    for(int i = 1; i < length.nums;i++){
        if(nums[i] > 0){
            dp[i][0]= dp[i-1][0] * nums[i];
            dp[i][1] = dp[i-1][1] * nums[i];
        }
        else{
             dp[i][0] = dp[i-1][1] * nums[i];
             dp[i][1] = dp[i-1][0] * nums[i];
        }
        res = max(dp[i][0],res);
    }
    return res;
}

滚动数据
x = i%2;
y = (i-1)%2;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值