zoukankan      html  css  js  c++  java
  • 后台开发 3个题目 array_chunk, 100块钱找零钱(动态规划 dynamic programming), 双向循环链表 llist 删除节点

    1. array_chunk 实现

       http://php.net/manual/en/function.array-chunk.php

    <?php
    function my_array_chunk($a, $sz) {
    	$b = [];
    	if ($sz < 1) {
            throw new Exception("size is less than 1");
    		return null;
    	}
    	for ($i = 0, $n = count($a); $i < $n; $i++) {
    		if ($i % $sz === 0) {
    			array_push($b, []);
    		}
    		array_push($b[count($b) - 1], $a[$i]);
    	}
    	return $b;
    }
    

      

      test:

    $input_array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
    print_r(my_array_chunk($input_array, 3));
    // print_r(my_array_chunk($input_array, 2));
    test my_array_chunk()

      output: 

    E:codephp>php chunk.php
    Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
                [2] => c
            )
    
        [1] => Array
            (
                [0] => d
                [1] => e
                [2] => f
            )
    
        [2] => Array
            (
                [0] => g
                [1] => h
            )
    
    )
    php chunk.php

      javascript:

    Array.prototype.chunk = function(sz) {
        var a = [];
        if (sz<1) {
           	throw new Error("size is less than 1");
        }
        this.forEach(function(e, i) {
            if (i % sz === 0) {
                a.push([]);
            }
            a[a.length-1].push(e);         
        });
        return a;
    };
    

      

      test:

    var a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
    console.log(a.chunk(2));
    console.log(a.chunk(1));
    console.log(a.chunk(8));
    console.log(a.chunk(10));
    console.log(a.chunk(0));
    test Array.prototype.chunk

      output:

    E:codejsalgorithm>node array_chunk.js
    [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ], [ 'g', 'h' ] ]
    [ [ 'a' ],
      [ 'b' ],
      [ 'c' ],
      [ 'd' ],
      [ 'e' ],
      [ 'f' ],
      [ 'g' ],
      [ 'h' ] ]
    [ [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ] ]
    [ [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ] ]
    [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ]
    output for Array.prototype.chunk

    * golang

    // HelloWorld project main.go

    package main
    
    import (
    	"fmt"
    )
    
    func array_chunk(a []string, sz int) [][]string {
    	var n int = len(a)/sz   // 二维数组的长度
        if (len(a)>n*sz) { n += 1 }
    	var b = make([][]string, 0, n)
    
    	for i := 0; i < len(a); i++ {
    		offset := i % sz
    		if offset == 0 {
    			b = append(b, make([]string, sz))
    		}
    		b[len(b)-1][offset] = a[i]
    	}
    	return b
    }
    
    func slice2d_toString(a [][]string) string {
    	s := "["
    
    	for i := 0; i < len(a); i++ {
    		s += "["
    		j := 0
    		for ; j < len(a[i])-1; j++ {
    			s += a[i][j] + ","
    		}
    		s += a[i][j] + "] "
    	}
    
    	s += "]"
    	return s
    }
    
    func main() {
    	letters := []string{"a", "b", "c", "d", "e", "f", "g"}
    	a2d := array_chunk(letters, 3)
    	fmt.Printf(slice2d_toString(a2d))
    }
    

      output:

    C:/go/bin/go.exe build -i [J:/gocode/src/HelloWorld]
    成功: 进程退出代码 0.
    J:/gocode/src/HelloWorld/HelloWorld.exe  [J:/gocode/src/HelloWorld]
    [[a,b,c] [d,e,f] [g,,] ]成功: 进程退出代码 0.
    go output

    Java:

    package cn.mediamix;
    
    import java.util.ArrayList;
    
    public class ArrayChunk {
    	
    	private static ArrayList<ArrayList<String>> arrayChunk(String[] input, int sz) 
    			throws Exception {
    		ArrayList<ArrayList<String>> a = new ArrayList<ArrayList<String>>();
    		if (sz < 1) {
    			throw new Exception("size is less than 1");
    		}
    		for (int i = 0, n = input.length; i < n; i++) {
    			if (i % sz == 0) {
    				a.add(new ArrayList<String>());
    			}
    			a.get(a.size()-1).add(input[i]);
    		}
    		
    		return a;
    	}
    
    	public static void main(String[] args) {
    		String[] input = {"a", "b", "c", "d", "e", "f", "g", "h"};
    		ArrayList<ArrayList<String>> a = null;
    		try {
    			a = arrayChunk(input, 3);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		System.out.println(a.toString());
    	}
    }
    

      Output: 

    [[a, b, c], [d, e, f], [g, h]]

    2. 100块钱 找零钱多少种方法  50, 20, 10, 5, 1

       查一下贪心算法、0/1背包问题  (343种, 但是套4层循环不是好的方法)

      先看一个简单一点的问题: 93块钱找零钱,用最少的note/coins数怎么做?

    function findMin(deno, v) {
        deno = deno.sort(function(a, b) {
           return b-a;
        });
        var ans = [];
        deno.forEach(function(item) {
            while (v >= item) {
                v -= item;
                ans.push(item);
            }
        });
        return ans;
    }
    
    var deno = [50, 20, 10, 5, 1];
    console.log(findMin(deno, 93));
    

      output: 

    [ 50, 20, 20, 1, 1, 1 ]

    100块钱, 用面值 [ 50, 20, 10, 5, 1 ]的钱币, 换零钱多少种方法?

    用动态规划法:

    php:

    <?php
    function coins($deno, $v) {
        $n = count($deno);
        $dp = [];
        for ($i = 0; $i < $n; $i++) {
            $dp[$i] = [];  // length: $v+1
            $dp[$i][0] = 1; //第一列为1
        }
        for ($j = 0; $j <= $v; $j++) {
            // 第一行中能够被$deno[0]整除的数,即可以被换钱,记为1
            $dp[0][$j] = $j % $deno[0]===0 ? 1 : 0;
        }
        for ($i = 1; $i < $n; $i++) {
            for ($j = 1; $j <= $v; $j++) {
                $tmp = 0;
                for ($k = 0; $k * $deno[$i] <= $j; $k++) {
                    // 累加用$k张$deno[i]货币后$dp[i-1]中组成剩下钱数的方法数
                    $tmp += $dp[$i-1][ $j - $k * $deno[$i] ];
                }
                $dp[$i][$j] = $tmp;
            }
        }
        return $dp[$n-1][$v];
    }
    
    // test
    $deno = [50,20,10,5,1];
    echo coins($deno, 100).PHP_EOL;
    

      

    javascript:

    function coins(deno, v) {
        if (deno === null || deno.length === 0 || v < 0) {
            return 0;
        }
        var dp = new Array(v + 1);
        // init
        for (var i = 0; i < dp.length; i++) {
            dp[i] = 0;
        }
        for (var j = 0; deno[0] * j <= v; j++) {
            dp[deno[0] * j] = 1;
        }
        for (i = 1; i < deno.length; i++) {
            for (j = 1; j <= v; j++) {
                dp[j] += j - deno[i] >= 0 ? dp[j - deno[i]] : 0;
            }
        }
        return dp[v];
    }
    

      

    // test
    var deno = [50, 20, 10, 5, 1];
    console.log(coins(deno, 100));  // 343

    golang: 

    // Dynamic programming project main.go
    package main
    
    import (
    	"fmt"
    )
    
    func coin(deno []int, v int) int {
    	n := len(deno)
    	dp := make([][]int, 0, n)
    	for i := 0; i < n; i++ {
    		dp = append(dp, make([]int, v+1))
    		dp[i][0] = 1
    	}
    	for j := 0; j <= v; j++ {
    		if j%deno[0] == 0 {
    			dp[0][j] = 1
    		} else {
    			dp[0][j] = 0
    		}
    	}
    	for i := 1; i < n; i++ {
    		for j := 1; j <= v; j++ {
    			tmp := 0
    			for k := 0; k*deno[i] <= j; k++ {
    				tmp += dp[i-1][j-k*deno[i]]
    			}
    			dp[i][j] = tmp
    		}
    	}
    	return dp[n-1][v]
    }
    
    func main() {
    	deno := make([]int, 0, 5)
    	deno = append(deno, 50, 20, 10, 5, 1)
    
    	/*
    		for i := range deno {
    			fmt.Println(deno[i])
    		}
    	*/
    	c := coin(deno, 100)
    	fmt.Println(c)
    }
    

      output:

    /usr/local/go/bin/go build -i [/Users/Mch/Code/golang/src/Greedy]
    Success: process exited with code 0.
    /Users/Mch/Code/golang/src/Greedy/Greedy  [/Users/Mch/Code/golang/src/Greedy]
    343
    Success: process exited with code 0.
    main.go output

    Java:

    package cn.mediamix;
    
    public class Coins {
    	
    	public static int coins(int []deno, int v) {
    		if (deno == null || deno.length == 0 || v < 0) {
    			return 0;
    		}
    		int[] dp = new int[v+1];
    		for (int j = 0; deno[0] * j <= v; j++) {
    			dp[deno[0]*j] = 1;
    		}
    		for (int i = 1; i < deno.length; i++) {
    			for (int j = 1; j <= v; j++) {
    				dp[j] += j - deno[i] >= 0 ? dp[j-deno[i]] : 0;
    			}
    		}
    		return dp[v];
    	}
    
    	public static void main(String[] args) {
    		int []deno = {50, 20, 10, 5, 1};
    		int solutions = Coins.coins(deno, 100);
    		System.out.println(solutions);
    	}
    
    }

      output:  343 

    3. 双向链表删除节点 (只有1个节点怎么处理)

       为了让链表的元素适应任何类型, 参照内核链表. http://kernel.org

        ~/linux-4.17.11/include/linux/list.h

        ~/linux-4.17.11/include/linux/kernel.h

        ~/linux-4.17.11/include/linux/stddef.h

        ~/linux-4.17.11/include/linux/poison.h

      llist.h

    #ifndef llist_h
    #define llist_h
    
    struct list_head {
        struct list_head *next;
        struct list_head *prev;
    };
    
    // #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
    
    #define list_entry(ptr, type, member)  
    container_of(ptr, type, member)
    
    #define container_of(ptr, type, member) ({ 
    void *__mptr = (void *)(ptr);   
    ((type *)(__mptr - offsetof(type, member))); })
    
    #define LIST_HEAD_INIT(name) { &(name), &(name) }
    
    #define LIST_HEAD(name) 
    struct list_head name = LIST_HEAD_INIT(name)
    
    static inline void INIT_LIST_HEAD(struct list_head *list)
    {
        list->next = list;
        list->prev = list;
    }
    
    static inline void __list_add(struct list_head *new,
                                  struct list_head *prev,
                                  struct list_head *next)
    {
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
    }
    
    static inline void list_add_tail(struct list_head *new, struct list_head *head)
    {
        __list_add(new, head->prev, head);
    }
    
    static inline void list_add(struct list_head *new, struct list_head *head)
    {
        __list_add(new, head, head->next);
    }
    
    static inline void __list_del(struct list_head * prev, struct list_head * next)
    {
        next->prev = prev;
        prev->next = next;
    }
    
    static inline void __list_del_entry(struct list_head *entry)
    {
        // if (!__list_del_entry_valid(entry)) return;
        __list_del(entry->prev, entry->next);
    }
    
    #define POISON_POINTER_DELTA 0
    
    #define LIST_POISON1  ((void *) 0x100 + POISON_POINTER_DELTA)
    #define LIST_POISON2  ((void *) 0x200 + POISON_POINTER_DELTA)
    
    static inline void list_del(struct list_head *entry)
    {
        __list_del_entry(entry);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
    }
    

      

    main.c

    #include <stdio.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include "llist.h"
    
    struct fox {
        unsigned long tail_length;
        unsigned long weight;
        bool is_fantastic;
        struct list_head list;
    };
    
    void handler(struct fox *f) {
        printf("tail length: %lu, weight=%lu, fantasic: %d
    ",
               f->tail_length, f->weight, f->is_fantastic?1:0);
    }
    
    struct fox *list_traverse(const struct list_head *fox_list,
                              void (*handler)(struct fox *f)) {
        // 链表指针(不包含元素)迭代器
        struct list_head *p;
        // 链表整个节点迭代器
        struct fox *f = NULL;
        
        list_for_each(p, fox_list) {
            f = list_entry(p, struct fox, list);
            handler(f);
        }
        return f;
    }
    
    int main(int argc, const char * argv[]) {
        /*
        struct fox *red_fox = (struct fox *)malloc(sizeof(*red_fox));    
        red_fox->tail_length = 40;
        red_fox->weight = 6;
        red_fox->is_fantastic = false;
        INIT_LIST_HEAD(&red_fox->list);
        */
        struct fox red_fox = {
            .tail_length = 40,
            .weight = 6,
            .is_fantastic = false,
            .list = LIST_HEAD_INIT(red_fox.list)
        };
        
        struct fox new_fox = {
            .tail_length = 35,
            .weight = 5,
            .is_fantastic = true,
            .list = LIST_HEAD_INIT(new_fox.list)
        };
        // 初始化表头
        LIST_HEAD(fox_list);
        // 添加2个节点
        list_add_tail(&red_fox.list, &fox_list);
        list_add_tail(&new_fox.list, &fox_list);
        
        struct fox *f = list_traverse(&fox_list, handler);
        
        // 删除最后添加的一个节点
        list_del(&f->list);
        printf("after deleted
    ");
        f = list_traverse(&fox_list, handler);
        
        // 同理再删除一个节点
        list_del(&f->list);
        printf("after deleted
    ");
        list_traverse(&fox_list, handler);
        
        return 0;
    }
    

      output:

    tail length: 40, weight=6, fantasic: 0

    tail length: 35, weight=5, fantasic: 1

    after deleted

    tail length: 40, weight=6, fantasic: 0

    after deleted

    Program ended with exit code: 0

  • 相关阅读:
    古谚、评论与论断、名篇与名言
    重读《西游记》
    重读《西游记》
    命名之法 —— 时间、季节、地点
    命名之法 —— 时间、季节、地点
    文言的理解 —— 古时的称谓、别称、别名
    文言的理解 —— 古时的称谓、别称、别名
    Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration
    瀑布 敏捷 文档
    POJ 1325 ZOJ 1364 最小覆盖点集
  • 原文地址:https://www.cnblogs.com/mingzhanghui/p/9377552.html
Copyright © 2011-2022 走看看