簡體   English   中英

查找所有組合

[英]Find all combinations

我的老師問一個找到所有組合的算法。 我有一組數據,長度可以變化。 所以組合應該是這樣的:

a
b
c
aa
ab
ac
...
ccbc
ccca
cccb
cccc

它們將存儲在包含單個varchar字段的“單詞”表中。 我這樣做是因為循環,因為我不喜歡遞歸並且jt的性能更好:

DROP PROCEDURE combi;
CREATE PROCEDURE combi
AS
BEGIN
    DELETE FROM word
    DECLARE @i BIGINT
    DECLARE @j INT
    DECLARE @word NVARCHAR(24)
    DECLARE @str NVARCHAR(62)
    DECLARE @combinations BIGINT
    DECLARE @currentlength TINYINT
    DECLARE @maxcurrentlength TINYINT
    SET @maxcurrentlength=4
    SET @str='azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789' -- length=62
    SET @currentlength=1
    -- loop on the length of the text
    WHILE @currentlength<=@maxcurrentlength BEGIN
        SET @combinations=POWER(62,@currentlength)
        SET @i=0
        -- get all combinations
        WHILE i<@combinations BEGIN
            SET @word=''
            SET @j=0
            -- generate word
            WHILE @j<@currentlength BEGIN
                SET @word=@word+SUBSTRING(@str, (FLOOR(@i / POWER(62,@currentlength-@j-1) ) % 62) +1, 1)
                SET @j=@j+1
            END
            INSERT INTO word VALUES (@word)
            SET @i=@i+1
        END
        SET @currentlength=@currentlength+1
    END
END;
EXEC combi;

問題是當我使用長度為8的服務器時,服務器崩潰了:似乎是POWER(62,@currentlength-@j-1)了問題。

我對你如何問這個問題有些困惑。 您要求“查找所有組合”,這可以使用CROSS JOIN輕松完成。 如果您需要獲得4的長度,則將具有可用值的表自身連接4次,您已經完成了很多工作。 如果需要在1字段中獲取字符串,則可以在選擇中將它們連接起來。 像這樣:

declare @values table (
value nvarchar(100))

insert @values values ('a'),('b'),('c')

select v1.value+v2.value+v3.value+v4.value
from @values v1 cross join 
    @values v2 cross join
    @values v3 cross join
    @values v4
order by v1.value+v2.value+v3.value+v4.value

這是使用遞歸CTE通用解決方案

CREATE TABLE t (i nchar(1))
INSERT INTO t VALUES ('a'),('b'),('c')

;WITH cte AS (
   SELECT cast(i AS nvarchar(4000)) AS combo, 1 AS ct
   FROM   t

   UNION  ALL
   SELECT cte.combo + t.i, ct + 1
   FROM   cte
   CROSS  JOIN t
   WHERE  ct <= 4  -- your maximum length
   )
SELECT combo
FROM   cte
ORDER  BY ct, combo

SQL提琴。

您必須注意,結果數隨着最大長度的增加而呈指數增長 ,因此,隨着最大長度的增加,性能會迅速下降。

您可能會溢出傳遞給POWER()的int類型, 因為power文檔建議POWER()返回與您提供的類型相同的類型。

嘗試使用:

SET @word=@word+SUBSTRING(@str, (FLOOR(@i / POWER(CAST(62 AS BIGINT),@currentlength-@j-1) ) % 62) +1, 1)

如果需要對其進行參數化,以便可以設置所需的長度,則此算法可以實現,並且它更面向關系數據庫。

declare @characters table (character nchar(1))
declare @words table (word nvarchar(100))
insert @characters values ('a'),('b'),('c')
INSERT @words (word ) VALUEs ('')
DECLARE @Required_length int
DECLARE @length int
SET @Required_length = 4
SET @length  = 0
WHILE @length <= @Required_length
BEGIN
SET @length  = @length+1
INSERT @words (word ) 
SELECT w.word + c.character
FROM @words w JOIN  @characters c ON LEN(w.word) = @length-1
END
SELECT word from @words where len(word) = @Required_length
  • 以長度為零的單詞開頭
  • 將所有可能的字符添加到零長度單詞中,以獲取所有一個字符單詞
  • 將所有可能的字符添加到所有一個字符單詞的末尾以獲取所有兩個字符單詞
  • 將所有可能的字符添加到所有兩個字符詞的末尾以獲取所有三個字符詞
  • 等等....

您可以通過將長度作為單詞表中的一列包括在內來使其更有效地運行,從而在您按長度進行過濾時無需計算長度,但是由於這是您的老師設置的,我不會為你做所有的工作

首先插入所有字符

SET NOCOUNT ON;
create table ##chars (col char(1))
declare @i int 
set @i=65
while @i<=90  /* A-Z */
begin
  insert into ##chars values( CHAR(@i))
  set @i=@i+1
end
set @i=97
while @i<=122 /* a-z */
begin
  insert into ##chars values( CHAR(@i))
  set @i=@i+1
end
set @i=48
while @i<=57  /* 0-9 */
begin
  insert into ##chars values( CHAR(@i))
  set @i=@i+1
end

現在,設置組合編號

create table ##result(word varchar(10))
declare @wide int
set @wide=4    /* set how many combinations are calculated  */


insert into ##result select * from ##chars
while @wide>1
begin
    begin tran w
    insert into ##result select a.word+b.col from ##result a, ##chars b
    commit tran w
set @wide=@wide-1
end
select * from ##result
/*
drop table ##chars
drop table ##result
*/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM